Commit 0c4db51f authored by Ulysse Beaugnon's avatar Ulysse Beaugnon

Merge branch 'master' of https://git.erp5.org/repos/vifibnet

Conflicts:
	TODO
	tunnel.py
parents f6bcf05c 27a5abf6
...@@ -154,7 +154,7 @@ OPTIONS : VIFIBNET.PY ...@@ -154,7 +154,7 @@ OPTIONS : VIFIBNET.PY
line, vifibnet will attempt to forward a port with upnp for each line, vifibnet will attempt to forward a port with upnp for each
couple port/proto given. couple port/proto given.
Protocols should be either udp or tcp-server. Protocols should be either udp or tcp-server.
Default : (1194, udp) Default : (1194, udp), (1194, tcp-server)
--tunnel-refresh duration --tunnel-refresh duration
Interval in seconds between two tunnel refresh. Refreshing tunnels Interval in seconds between two tunnel refresh. Refreshing tunnels
......
To be done : URGENT => Name ideas :
use the server as a bootstrap node -> switch peer discovery to be done resnet ( for Resiliable NET )
by vifibnet directly ? rsnet ( Resiliable Scalable NET )
To be done :
Use an algorithm to choose which connections to keep and/or establish Use an algorithm to choose which connections to keep and/or establish
instead of pure randomness instead of pure randomness
number of routes / tunnel number of routes / tunnel
favorise most used roads favorise most used roads
Write docstrings for all class/methods/functions Write docstrings for all class/methods/functions
Handle corrupt peers DB gracefully
To be discussed: To be discussed:
U : Babel seems to be very long to establish the routes : maybe we should U : Babel seems to be very long to establish the routes : maybe we should
......
...@@ -28,6 +28,11 @@ class PeerManager: ...@@ -28,6 +28,11 @@ class PeerManager:
utils.log('Preparing peers database...', 4) utils.log('Preparing peers database...', 4)
try: try:
self._db.execute("UPDATE peers SET used = 0") self._db.execute("UPDATE peers SET used = 0")
self._db.execute("""CREATE TABLE IF NOT EXISTS blacklist (
prefix TEXT PRIMARY KEY,
flag INTEGER NOT NULL)""")
self._db.execute("""CREATE INDEX IF NOT EXISTS
blacklist_flag ON blacklist(flag)""")
except sqlite3.OperationalError, e: except sqlite3.OperationalError, e:
if e.args[0] == 'no such table: peers': if e.args[0] == 'no such table: peers':
raise RuntimeError raise RuntimeError
...@@ -35,13 +40,22 @@ class PeerManager: ...@@ -35,13 +40,22 @@ class PeerManager:
self.next_refresh = time.time() self.next_refresh = time.time()
def reset_blacklist(self): def clear_blacklist(self, flag):
self._blacklist = [(self._prefix)] utils.log('Clearing blacklist from flag %u' % (flag,), 3)
self._db.execute("DELETE FROM blacklist WHERE flag = ?", (flag,))
utils.log('Blacklist cleared', 5)
def blacklist(self, prefix): def blacklist(self, prefix, flag):
utils.log('Blacklisting %s' % (prefix,), 4) utils.log('Blacklisting %s' % (prefix,), 4)
self._db.execute("DELETE FROM peers WHERE prefix = ?", (prefix,)) self._db.execute("DELETE FROM peers WHERE prefix = ?", (prefix,))
self._blacklist = list(set(self._blacklist + [(prefix,)])) self._db.execute("INSERT OR REPLACE INTO blacklist VALUES (?,?)",
(prefix, flag))
utils.log('%s blacklisted' % (prefix,), 5)
def whitelist(self, prefix):
utils.log('Unblacklisting %s' % (prefix,), 4)
self._db.execute("DELETE FROM blacklist WHERE prefix = ?", (prefix,))
utils.log('%s whitelisted' % (prefix,), 5)
def refresh(self): def refresh(self):
utils.log('Refreshing the peers DB...', 2) utils.log('Refreshing the peers DB...', 2)
...@@ -74,8 +88,8 @@ class PeerManager: ...@@ -74,8 +88,8 @@ class PeerManager:
(str(len(new_peer_list) - self._db_size),)) (str(len(new_peer_list) - self._db_size),))
self._db.executemany("""INSERT OR IGNORE INTO peers (prefix, address) self._db.executemany("""INSERT OR IGNORE INTO peers (prefix, address)
VALUES (?,?)""", new_peer_list) VALUES (?,?)""", new_peer_list)
self._db.executemany("DELETE FROM peers WHERE prefix = ?", self._db.execute("""DELETE FROM peers WHERE prefix IN
self._blacklist) (SELECT prefix FROM blacklist)""")
utils.log('DB populated', 3) utils.log('DB populated', 3)
utils.log('New peers : %s' % ', '.join(map(str, new_peer_list)), 5) utils.log('New peers : %s' % ', '.join(map(str, new_peer_list)), 5)
...@@ -121,3 +135,4 @@ class PeerManager: ...@@ -121,3 +135,4 @@ class PeerManager:
else: else:
utils.log('Unknow message recieved from the openvpn pipe : ' utils.log('Unknow message recieved from the openvpn pipe : '
+ msg, 1) + msg, 1)
...@@ -55,6 +55,9 @@ class main(object): ...@@ -55,6 +55,9 @@ class main(object):
help='Path to certificate key') help='Path to certificate key')
_('--mailhost', required=True, _('--mailhost', required=True,
help='SMTP server mail host') help='SMTP server mail host')
_('--bootstrap', nargs=4, action="append",
help='''VPN prefix, ip address, port and protocol to send as
bootstrap peers, instead of random ones''')
self.config = parser.parse_args() self.config = parser.parse_args()
# Database initializing # Database initializing
...@@ -180,8 +183,14 @@ class main(object): ...@@ -180,8 +183,14 @@ class main(object):
# TODO: Insert a flag column for bootstrap ready servers in peers # TODO: Insert a flag column for bootstrap ready servers in peers
# ( servers which shouldn't go down or change ip and port as opposed to servers owned by particulars ) # ( servers which shouldn't go down or change ip and port as opposed to servers owned by particulars )
# that way, we also ascertain that the server sent is not the new node.... # that way, we also ascertain that the server sent is not the new node....
prefix, address = self.db.execute("SELECT prefix, address FROM peers ORDER BY random() LIMIT 1").next() if self.config.bootstrap:
print "Sending bootstrap peer (%s, %s)" % (prefix, str(address)) bootpeer = random.choice(self.config.bootstrap)
prefix = bootpeer[0]
address = ','.join(bootpeer[1:])
else:
prefix, address = self.db.execute("""SELECT prefix, address
FROM peers ORDER BY random() LIMIT 1""")
print "Sending bootstrap peer (%s, %s)" % (prefix, address)
return prefix, address return prefix, address
def declare(self, handler, address): def declare(self, handler, address):
......
...@@ -7,7 +7,6 @@ smooth = 0.3 # this is used to smooth the traffic sampling. Lower value ...@@ -7,7 +7,6 @@ smooth = 0.3 # this is used to smooth the traffic sampling. Lower value
protected = 0.2 # ratio of the tunnels protected against kill because they are protected = 0.2 # ratio of the tunnels protected against kill because they are
# used a lot # used a lot
# Be carfull the refresh interval should let the routes be established # Be carfull the refresh interval should let the routes be established
...@@ -35,9 +34,13 @@ class Connection: ...@@ -35,9 +34,13 @@ class Connection:
% (self._prefix, self.process.returncode), 3) % (self._prefix, self.process.returncode), 3)
return False return False
self._updateBandwidth() # self._updateBandwidth()
return True return True
# Unused for now. By killing tunnels with significantly lower trafic
# in comparison to other tunnels, we hope to connect to nodes with
# better bandwith, in order to improve connectivity with destinations
# we are really interested in.
def _updateBandwidth(self): def _updateBandwidth(self):
try: try:
f_rx = open('/sys/class/net/%s/statistics/rx_bytes' % f_rx = open('/sys/class/net/%s/statistics/rx_bytes' %
...@@ -81,7 +84,6 @@ class TunnelManager: ...@@ -81,7 +84,6 @@ class TunnelManager:
self._network = network self._network = network
self._net_len = len(network) self._net_len = len(network)
self._iface_list = iface_list self._iface_list = iface_list
self.__indirect_connect = []
self.free_interface_set = set(('client1', 'client2', 'client3', self.free_interface_set = set(('client1', 'client2', 'client3',
'client4', 'client5', 'client6', 'client4', 'client5', 'client6',
'client7', 'client8', 'client9', 'client7', 'client8', 'client9',
...@@ -154,18 +156,16 @@ class TunnelManager: ...@@ -154,18 +156,16 @@ class TunnelManager:
def _countRoutes(self): def _countRoutes(self):
utils.log('Starting to count the routes on each interface...', 3) utils.log('Starting to count the routes on each interface...', 3)
self._indirect_connect = [] self._peer_db.clear_blacklist(0)
for iface in self._iface_to_prefix.keys(): for iface in self._iface_to_prefix.keys():
self._connection_dict[self._iface_to_prefix[iface]].routes = 0 self._connection_dict[self._iface_to_prefix[iface]].routes = 0
f = open('/proc/net/ipv6_route', 'r') for line in open('/proc/net/ipv6_route'):
for line in f: line = line.split()
ip, subnet_size, iface = struct.unpack('32s x 2s 106x %ss x' ip = bin(int(line[0], 16))[2:].rjust(128, '0')
% (len(line) - 142), line)
ip = bin(int(ip, 16))[2:].rjust(128, '0')
if ip.startswith(self._network): if ip.startswith(self._network):
iface = iface.strip() iface = line[-1]
subnet_size = int(subnet_size, 16) subnet_size = int(line[1], 16)
utils.log('Route on iface %s detected to %s/%s' utils.log('Route on iface %s detected to %s/%s'
% (iface, ip, subnet_size), 8) % (iface, ip, subnet_size), 8)
if iface in self._iface_to_prefix.keys(): if iface in self._iface_to_prefix.keys():
...@@ -174,7 +174,7 @@ class TunnelManager: ...@@ -174,7 +174,7 @@ class TunnelManager:
prefix = ip[self._net_len:subnet_size] prefix = ip[self._net_len:subnet_size]
utils.log('A route to %s has been discovered on the LAN' utils.log('A route to %s has been discovered on the LAN'
% (prefix,), 3) % (prefix,), 3)
self._peer_db.blacklist(prefix) self._peer_db.blacklist(prefix, 0)
utils.log("Routes have been counted", 3) utils.log("Routes have been counted", 3)
for p in self._connection_dict.keys(): for p in self._connection_dict.keys():
...@@ -185,3 +185,4 @@ class TunnelManager: ...@@ -185,3 +185,4 @@ class TunnelManager:
def killAll(self): def killAll(self):
for prefix in self._connection_dict.keys(): for prefix in self._connection_dict.keys():
self._kill(prefix) self._kill(prefix)
...@@ -85,7 +85,7 @@ def main(): ...@@ -85,7 +85,7 @@ def main():
# Get arguments # Get arguments
config = getConfig() config = getConfig()
if not config.pp: if not config.pp:
config.pp = [['1194', 'udp']] config.pp = [['1194', 'udp'], ['1194', 'tcp-server']]
manual = bool(config.address) manual = bool(config.address)
network = utils.networkFromCa(config.ca) network = utils.networkFromCa(config.ca)
internal_ip, prefix = utils.ipFromCert(network, config.cert) internal_ip, prefix = utils.ipFromCert(network, config.cert)
...@@ -137,7 +137,7 @@ def main(): ...@@ -137,7 +137,7 @@ def main():
# Establish connections # Establish connections
server_process = list(plib.server(internal_ip, len(network) + len(prefix), server_process = list(plib.server(internal_ip, len(network) + len(prefix),
config.connection_count, config.dh, write_pipe, port, config.connection_count, config.dh, write_pipe, port,
proto, config.hello, '--dev', 'vifibnet', *openvpn_args, proto, config.hello, '--dev', 'vifibnet-%s' % proto, *openvpn_args,
stdout=os.open(os.path.join(config.log, stdout=os.open(os.path.join(config.log,
'vifibnet.server.%s.log' % (proto,)), 'vifibnet.server.%s.log' % (proto,)),
os.O_WRONLY | os.O_CREAT | os.O_TRUNC), os.O_WRONLY | os.O_CREAT | os.O_TRUNC),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment