Commit 35b9ec40 authored by Ulysse Beaugnon's avatar Ulysse Beaugnon

--ping-exit option in openvpn has been restored so their is no more zombies connections

the --ip argument is now optional : it can be discovered automaticaly
parent 6a8fa1f1
...@@ -4,6 +4,7 @@ Bugs : ...@@ -4,6 +4,7 @@ Bugs :
When no peer is avalaible without the --no-boot option, it crash => see below When no peer is avalaible without the --no-boot option, it crash => see below
Once in a while, when exiting vifibnet ( not very properly, via Ctrl+C ), processes ( openvpn and babel ) Once in a while, when exiting vifibnet ( not very properly, via Ctrl+C ), processes ( openvpn and babel )
still remain and disturb further attemps ( must be killed for vifibnet to work again ) still remain and disturb further attemps ( must be killed for vifibnet to work again )
Babel seems to be very long to establish the routes : maybe we should tell him thant we are not on a wired network but on a mobile network ?
To be done : To be done :
Replace comments at the beginning of functions with docstrings & give all fn docstrings Replace comments at the beginning of functions with docstrings & give all fn docstrings
...@@ -12,6 +13,7 @@ To be done : ...@@ -12,6 +13,7 @@ To be done :
Use the server events ( client connection/deconnection ) to do something usefull Use the server events ( client connection/deconnection ) to do something usefull
In peers DB, remove some peers when they are too many of them In peers DB, remove some peers when they are too many of them
Contact the server using vifibnet and not the underlying network when possible Contact the server using vifibnet and not the underlying network when possible
Use a timeout for the peersDB
To be discuss: To be discuss:
U : Remove the --no-boot option since we know when no node is avalaible U : Remove the --no-boot option since we know when no node is avalaible
...@@ -30,3 +32,5 @@ To be discuss: ...@@ -30,3 +32,5 @@ To be discuss:
G : don't reconnect to server each time we repopulate in peers_db ? G : don't reconnect to server each time we repopulate in peers_db ?
U : we might recontact the server evry 1H or even less. So i think it is a good thing not to keep the connection alive U : we might recontact the server evry 1H or even less. So i think it is a good thing not to keep the connection alive
Why --ping-exit had been removed form openvpn args ? without this we can have zombie connections
...@@ -4,12 +4,13 @@ import utils ...@@ -4,12 +4,13 @@ import utils
class PeerManager: class PeerManager:
def __init__(self, dbPath, server, port, refresh_time): def __init__(self, dbPath, server, port, refresh_time, external_ip):
utils.log('Connectiong to peers database', 4) utils.log('Connectiong to peers database', 4)
self._db = sqlite3.connect(dbPath, isolation_level=None) self._db = sqlite3.connect(dbPath, isolation_level=None)
self._server = server self._server = server
self._port = port self._server_port = port
self._refresh_time = refresh_time self._refresh_time = refresh_time
self._external_ip = external_ip
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")
...@@ -18,16 +19,19 @@ class PeerManager: ...@@ -18,16 +19,19 @@ class PeerManager:
raise RuntimeError raise RuntimeError
self.next_refresh = time.time() self.next_refresh = time.time()
def populate(self, n, address): def populate(self, n, internal_ip, port, proto):
# address = (internal_ip, external_ip, port, proto) if self._external_ip != None:
address = (internal_ip, self._external_ip, port, proto)
else:
address = 0
utils.log('Connecting to remote server', 3) utils.log('Connecting to remote server', 3)
self._proxy = xmlrpclib.ServerProxy('http://%s:%u' % (self._server, self._port)) self._proxy = xmlrpclib.ServerProxy('http://%s:%u' % (self._server, self._server_port))
utils.log('Updating peers database : populating', 2) utils.log('Updating peers database : populating', 2)
_, external_ip, _, _ = address
new_peer_list = self._proxy.getPeerList(n, address) new_peer_list = self._proxy.getPeerList(n, address)
utils.log('New peers recieved from %s' % self._server, 5) utils.log('New peers recieved from %s' % self._server, 5)
self._db.executemany("INSERT OR IGNORE INTO peers (ip, port, proto, used) VALUES (?,?,?,0)", new_peer_list) self._db.executemany("INSERT OR IGNORE INTO peers (ip, port, proto, used) VALUES (?,?,?,0)", new_peer_list)
self._db.execute("DELETE FROM peers WHERE ip = ?", (external_ip,)) if self._external_ip != None:
self._db.execute("DELETE FROM peers WHERE ip = ?", (self._external_ip,))
self.next_refresh = time.time() + self._refresh_time self.next_refresh = time.time() + self._refresh_time
utils.log('New peers : %s' % ', '.join(map(str, new_peer_list)), 5) utils.log('New peers : %s' % ', '.join(map(str, new_peer_list)), 5)
...@@ -51,5 +55,6 @@ class PeerManager: ...@@ -51,5 +55,6 @@ class PeerManager:
utils.log('%s has disconnected' % (arg,), 3) utils.log('%s has disconnected' % (arg,), 3)
elif script_type == 'route-up': elif script_type == 'route-up':
utils.log('External Ip : ' + arg, 3) utils.log('External Ip : ' + arg, 3)
self._external_ip = arg
else: else:
utils.log('Unknow message recieved from the openvpn pipe : ' + msg, 1) utils.log('Unknow message recieved from the openvpn pipe : ' + msg, 1)
...@@ -11,12 +11,8 @@ def openvpn(*args, **kw): ...@@ -11,12 +11,8 @@ def openvpn(*args, **kw):
'--persist-key', '--persist-key',
'--script-security', '2', '--script-security', '2',
'--user', 'nobody', '--user', 'nobody',
# I don't kown how Babel works, but if it test the '--ping', '1',
# connection often, the ping directive might not be needed '--ping-exit', '3',
# if it test the connection very often, we could also decrease
# ping-exit to 1 sec
# '--ping', '1',
# '--ping-exit', '3',
'--group', 'nogroup', '--group', 'nogroup',
'--verb', str(verbose), '--verb', str(verbose),
] + list(args) ] + list(args)
...@@ -26,7 +22,7 @@ def openvpn(*args, **kw): ...@@ -26,7 +22,7 @@ def openvpn(*args, **kw):
# TODO : set iface up when creating a server/client # TODO : set iface up when creating a server/client
# ! check working directory before launching up script ? # ! check working directory before launching up script ?
def server(serverIp, network, max_clients, dh_path, pipe_fd, *args, **kw): def server(serverIp, network, max_clients, dh_path, pipe_fd, port, proto, *args, **kw):
utils.log('Starting server', 3) utils.log('Starting server', 3)
return openvpn( return openvpn(
'--tls-server', '--tls-server',
...@@ -36,6 +32,8 @@ def server(serverIp, network, max_clients, dh_path, pipe_fd, *args, **kw): ...@@ -36,6 +32,8 @@ def server(serverIp, network, max_clients, dh_path, pipe_fd, *args, **kw):
'--client-disconnect', 'ovpn-server ' + str(pipe_fd), '--client-disconnect', 'ovpn-server ' + str(pipe_fd),
'--dh', dh_path, '--dh', dh_path,
'--max-clients', str(max_clients), '--max-clients', str(max_clients),
'--port', str(port),
'--proto', proto,
*args, **kw) *args, **kw)
def client(serverIp, pipe_fd, *args, **kw): def client(serverIp, pipe_fd, *args, **kw):
......
...@@ -193,9 +193,10 @@ class main(object): ...@@ -193,9 +193,10 @@ class main(object):
def getPeerList(self, handler, n, address): def getPeerList(self, handler, n, address):
assert 0 < n < 1000 assert 0 < n < 1000
print "declaring new node" print "declaring new node"
if not self.declare(handler, address): if address != 0:
# TODO: do something intelligent if not self.declare(handler, address):
raise RuntimeError # TODO: do something intelligent
raise RuntimeError
print "sending peers" print "sending peers"
return self.db.execute("SELECT ip, port, proto FROM peers ORDER BY random() LIMIT ?", (n,)).fetchall() return self.db.execute("SELECT ip, port, proto FROM peers ORDER BY random() LIMIT ?", (n,)).fetchall()
......
...@@ -33,8 +33,8 @@ class TunnelManager: ...@@ -33,8 +33,8 @@ class TunnelManager:
if p.poll() != None: if p.poll() != None:
utils.log('Connection with %s has failed with return code %s' % (id, p.returncode), 3) utils.log('Connection with %s has failed with return code %s' % (id, p.returncode), 3)
self.free_interface_set.add(iface) self.free_interface_set.add(iface)
self.peer_db.unusePeer(id) self._peer_db.unusePeer(id)
del self.connection_dict[id] del self._connection_dict[id]
def _removeSomeTunnels(self): def _removeSomeTunnels(self):
for i in range(0, max(0, len(self._connection_dict) - self._client_count + self._refresh_count)): for i in range(0, max(0, len(self._connection_dict) - self._client_count + self._refresh_count)):
......
...@@ -30,8 +30,14 @@ def getConfig(): ...@@ -30,8 +30,14 @@ def getConfig():
help='Path to the certificate authority file') help='Path to the certificate authority file')
_('--cert', required=True, _('--cert', required=True,
help='Path to the certificate file') help='Path to the certificate file')
_('--ip', required=True, dest='external_ip', _('--ip', default=None, dest='external_ip',
help='Ip address of the machine on the internet') help='Ip address of the machine on the internet')
_('--internal-port', default=1194,
help='The internal port to listen on for incomming connections')
_('--external-port', default=1194,
help='The external port to advertise for other peers to connect')
_('--proto', default='udp',
help='The protocol to use for the others peers to connect')
# args to be removed ? # args to be removed ?
_('--connection-count', default=30, type=int, _('--connection-count', default=30, type=int,
help='Number of client connections') help='Number of client connections')
...@@ -49,10 +55,6 @@ def main(): ...@@ -49,10 +55,6 @@ def main():
internal_ip = utils.ipFromCert(network, config.cert) internal_ip = utils.ipFromCert(network, config.cert)
openvpn_args = utils.ovpnArgs(config.openvpn_args, config.ca, config.cert) openvpn_args = utils.ovpnArgs(config.openvpn_args, config.ca, config.cert)
# Get real port and proto ?
port = 1194
proto = 'udp'
# Set global variables # Set global variables
tunnel.log = config.log tunnel.log = config.log
utils.verbose = plib.verbose = config.verbose utils.verbose = plib.verbose = config.verbose
...@@ -63,7 +65,7 @@ def main(): ...@@ -63,7 +65,7 @@ def main():
read_pipe = os.fdopen(r_pipe) read_pipe = os.fdopen(r_pipe)
# Init db and tunnels # Init db and tunnels
peer_db = db.PeerManager(config.db, config.server, config.server_port, config.peers_db_refresh) peer_db = db.PeerManager(config.db, config.server, config.server_port, config.peers_db_refresh, config.external_ip)
tunnel_manager = tunnel.TunnelManager(write_pipe, peer_db, openvpn_args, config.tunnel_refresh, config.connection_count, config.refresh_rate) tunnel_manager = tunnel.TunnelManager(write_pipe, peer_db, openvpn_args, config.tunnel_refresh, config.connection_count, config.refresh_rate)
# Launch babel on all interfaces. WARNING : you have to be root to start babeld # Launch babel on all interfaces. WARNING : you have to be root to start babeld
...@@ -73,8 +75,8 @@ def main(): ...@@ -73,8 +75,8 @@ def main():
os.O_WRONLY | os.O_CREAT | os.O_TRUNC), stderr=subprocess.STDOUT) os.O_WRONLY | os.O_CREAT | os.O_TRUNC), stderr=subprocess.STDOUT)
# Establish connections # Establish connections
server_process = plib.server(internal_ip, network, config.connection_count, config.dh, write_pipe, server_process = plib.server(internal_ip, network, config.connection_count, config.dh, write_pipe,
'--dev', 'vifibnet', *openvpn_args, config.internal_port, config.proto, '--dev', 'vifibnet', *openvpn_args,
stdout=os.open(os.path.join(config.log, 'vifibnet.server.log'), os.O_WRONLY | os.O_CREAT | os.O_TRUNC)) stdout=os.open(os.path.join(config.log, 'vifibnet.server.log'), os.O_WRONLY | os.O_CREAT | os.O_TRUNC))
# main loop # main loop
...@@ -85,7 +87,7 @@ def main(): ...@@ -85,7 +87,7 @@ def main():
if ready: if ready:
peer_db.handle_message(read_pipe.readline()) peer_db.handle_message(read_pipe.readline())
if time.time() >= peer_db.next_refresh: if time.time() >= peer_db.next_refresh:
peer_db.populate(200, (internal_ip, config.external_ip, port, proto)) peer_db.populate(200, internal_ip, config.external_port, config.proto)
if time.time() >= tunnel_manager.next_refresh: if time.time() >= tunnel_manager.next_refresh:
tunnel_manager.refresh() tunnel_manager.refresh()
except KeyboardInterrupt: except KeyboardInterrupt:
......
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