Use lowercase for variables
[re6stnet.git] / vifibnet.py
1 #!/usr/bin/env python
2 import argparse, errno, math, os, select, subprocess, sys, time, traceback, upnpigd
3 from OpenSSL import crypto
4 import db, plib, upnpigd, utils, tunnel
5
6 def getConfig():
7 parser = argparse.ArgumentParser(
8 description='Resilient virtual private network application')
9 _ = parser.add_argument
10 # Server address MUST be a vifib address ( else requests will be denied )
11 _('--server', required=True,
12 help='Address for peer discovery server')
13 _('--server-port', required=True, type=int,
14 help='Peer discovery server port')
15 _('-log', '-l', default='/var/log',
16 help='Path to vifibnet logs directory')
17 _('--tunnel-refresh', default=300, type=int,
18 help='the time (seconds) to wait before changing the connections')
19 _('--peers-db-refresh', default=3600, type=int,
20 help='the time (seconds) to wait before refreshing the peers db')
21 _('--db', default='/var/lib/vifibnet/peers.db',
22 help='Path to peers database')
23 _('--dh', required=True,
24 help='Path to dh file')
25 _('--babel-state', default='/var/lib/vifibnet/babel_state',
26 help='Path to babeld state-file')
27 _('--verbose', '-v', default=0, type=int,
28 help='Defines the verbose level')
29 _('--ca', required=True,
30 help='Path to the certificate authority file')
31 _('--cert', required=True,
32 help='Path to the certificate file')
33 _('--ip', default=None, dest='external_ip',
34 help='Ip address of the machine on the internet')
35 _('--internal-port', default=1194,
36 help='The internal port to listen on for incomming connections')
37 _('--external-port', default=1194,
38 help='The external port to advertise for other peers to connect')
39 _('--proto', default='udp',
40 help='The protocol to use for the others peers to connect')
41 # args to be removed ?
42 _('--connection-count', default=30, type=int,
43 help='Number of client connections')
44 _('--refresh-rate', default=0.05, type=float,
45 help='The ratio of connections to drop when refreshing the connections')
46 # Openvpn options
47 _('openvpn_args', nargs=argparse.REMAINDER,
48 help="Common OpenVPN options (e.g. certificates)")
49 return parser.parse_args()
50
51 def main():
52 # Get arguments
53 config = getConfig()
54 network = utils.networkFromCa(config.ca)
55 internal_ip = utils.ipFromCert(network, config.cert)
56 openvpn_args = utils.ovpnArgs(config.openvpn_args, config.ca, config.cert)
57
58 # Set global variables
59 tunnel.log = config.log
60 utils.verbose = plib.verbose = config.verbose
61
62 # Create and open read_only pipe to get server events
63 utils.log('Creating pipe for server events', 3)
64 r_pipe, write_pipe = os.pipe()
65 read_pipe = os.fdopen(r_pipe)
66
67 # Init db and tunnels
68 if config.external_ip == None:
69 try:
70 config.external_ip, config.external_port = upnpigd.ForwardViaUPnP(config.internal_port)
71 except Exception:
72 utils.log('An atempt to forward a port via UPnP failed', 5)
73
74 peer_db = db.PeerManager(config.db, config.server, config.server_port, config.peers_db_refresh,
75 config.external_ip, internal_ip, config.external_port, config.proto, 200)
76 tunnel_manager = tunnel.TunnelManager(write_pipe, peer_db, openvpn_args, config.tunnel_refresh, config.connection_count, config.refresh_rate)
77
78 # Launch babel on all interfaces. WARNING : you have to be root to start babeld
79 interface_list = ['vifibnet'] + list(tunnel_manager.free_interface_set)
80 router = plib.router(network, internal_ip, interface_list,
81 stdout=os.open(os.path.join(config.log, 'vifibnet.babeld.log'),
82 os.O_WRONLY | os.O_CREAT | os.O_TRUNC), stderr=subprocess.STDOUT)
83
84 # Establish connections
85 server_process = plib.server(internal_ip, network, config.connection_count, config.dh, write_pipe,
86 config.internal_port, config.proto, '--dev', 'vifibnet', *openvpn_args,
87 stdout=os.open(os.path.join(config.log, 'vifibnet.server.log'), os.O_WRONLY | os.O_CREAT | os.O_TRUNC))
88
89 # main loop
90 try:
91 while True:
92 ready, tmp1, tmp2 = select.select([read_pipe], [], [],
93 max(0, min(tunnel_manager.next_refresh, peer_db.next_refresh) - time.time()))
94 if ready:
95 peer_db.handle_message(read_pipe.readline())
96 if time.time() >= peer_db.next_refresh:
97 peer_db.refresh()
98 if time.time() >= tunnel_manager.next_refresh:
99 tunnel_manager.refresh()
100 except KeyboardInterrupt:
101 return 0
102
103 if __name__ == "__main__":
104 main()
105