2 import argparse
, errno
, os
, select
, subprocess
, time
3 from argparse
import ArgumentParser
4 import db
, plib
, upnpigd
, utils
, tunnel
6 class ArgParser(ArgumentParser
):
8 def convert_arg_line_to_args(self
, arg_line
):
9 arg_line
= arg_line
.split('#')[0].rstrip()
11 if arg_line
.startswith('@'):
14 for arg
in ('--' + arg_line
.lstrip('--')).split():
18 def ovpnArgs(optional_args
, ca_path
, cert_path
):
19 # Treat openvpn arguments
20 if optional_args
[0] == "--":
22 optional_args
.append('--ca')
23 optional_args
.append(ca_path
)
24 optional_args
.append('--cert')
25 optional_args
.append(cert_path
)
30 parser
= ArgParser(fromfile_prefix_chars
='@',
31 description
='Resilient virtual private network application')
32 _
= parser
.add_argument
34 # General Configuration options
35 _('--ip', default
=None, dest
='address', action
='append', nargs
=3,
36 help='Ip address, port and protocol advertised to other vpn nodes')
37 _('--peers-db-refresh', default
=3600, type=int,
38 help='the time (seconds) to wait before refreshing the peers db')
39 _('-l', '--log', default
='/var/log',
40 help='Path to vifibnet logs directory')
41 _('-s', '--state', default
='/var/lib/vifibnet',
42 help='Path to VPN state directory')
43 _('-v', '--verbose', default
=0, type=int,
44 help='Defines the verbose level')
45 _('-i', '--interface', action
='append', dest
='iface_list', default
=[],
46 help='Extra interface for LAN discovery')
47 _('--server', required
=True,
48 help="VPN address of the discovery peer server")
49 _('--server-port', required
=True, type=int,
50 help="VPN port of the discovery peer server")
52 # Routing algorithm options
53 _('--hello', type=int, default
=15,
54 help='Hello interval for babel, in seconds')
55 _('-w', '--wireless', action
='store_true',
56 help='''Set all interfaces to be treated as wireless interfaces
57 for the routing protocol''')
60 _('--pp', nargs
=2, action
='append',
61 help='Port and protocol to be used by other peers to connect')
62 _('--tunnel-refresh', default
=300, type=int,
63 help='the time (seconds) to wait before changing the connections')
64 _('--dh', required
=True,
65 help='Path to dh file')
66 _('--ca', required
=True,
67 help='Path to the certificate authority file')
68 _('--cert', required
=True,
69 help='Path to the certificate file')
70 # args to be removed ?
71 _('--connection-count', default
=20, type=int,
72 help='Number of tunnels')
73 _('--refresh-rate', default
=0.05, type=float,
74 help='''The ratio of connections to drop when refreshing the
77 _('openvpn_args', nargs
=argparse
.REMAINDER
,
78 help="Common OpenVPN options (e.g. certificates)")
79 return parser
.parse_args()
86 config
.pp
= [['1194', 'udp']]
87 manual
= bool(config
.address
)
88 network
= utils
.networkFromCa(config
.ca
)
89 internal_ip
, prefix
= utils
.ipFromCert(network
, config
.cert
)
90 openvpn_args
= ovpnArgs(config
.openvpn_args
, config
.ca
, config
.cert
)
92 # Set global variables
93 tunnel
.log
= config
.log
94 utils
.verbose
= plib
.verbose
= config
.verbose
96 utils
.log("Configuration :\n" + str(config
), 5)
98 # Create and open read_only pipe to get server events
99 utils
.log('Creating pipe for server events...', 3)
100 r_pipe
, write_pipe
= os
.pipe()
101 read_pipe
= os
.fdopen(r_pipe
)
102 utils
.log('Pipe created', 5)
104 # Init db and tunnels
107 utils
.log('Detected manual external configuration', 3)
109 utils
.log('Attempting automatic configuration via UPnP...', 4)
111 forwarder
= upnpigd
.Forwarder()
113 for port
, proto
in config
.pp
:
114 ext
= forwarder
.AddRule(port
, proto
)
116 config
.address
.append(ext
)
117 except upnpigd
.NoUPnPDevice
:
118 utils
.log('No upnp device found', 4)
120 peer_db
= db
.PeerManager(config
.state
, config
.server
, config
.server_port
,
121 config
.peers_db_refresh
, config
.address
, internal_ip
, prefix
,
122 manual
, config
.pp
, 200)
123 tunnel_manager
= tunnel
.TunnelManager(write_pipe
, peer_db
, openvpn_args
,
124 config
.hello
, config
.tunnel_refresh
, config
.connection_count
,
125 config
.refresh_rate
, config
.iface_list
, network
)
127 # Launch routing protocol. WARNING : you have to be root to start babeld
128 interface_list
= ['vifibnet'] + list(tunnel_manager
.free_interface_set
) \
130 router
= plib
.router(network
, internal_ip
, interface_list
, config
.wireless
,
131 config
.hello
, os
.path
.join(config
.state
, 'vifibnet.babeld.state'),
132 stdout
=os
.open(os
.path
.join(config
.log
, 'vifibnet.babeld.log'),
133 os
.O_WRONLY | os
.O_CREAT | os
.O_TRUNC
), stderr
=subprocess
.STDOUT
)
135 # Establish connections
136 server_process
= list(plib
.server(internal_ip
, len(network
) + len(prefix
),
137 config
.connection_count
, config
.dh
, write_pipe
, port
,
138 proto
, config
.hello
, '--dev', 'vifibnet', *openvpn_args
,
139 stdout
=os
.open(os
.path
.join(config
.log
,
140 'vifibnet.server.%s.log' %
(proto
,)),
141 os
.O_WRONLY | os
.O_CREAT | os
.O_TRUNC
),
142 stderr
=subprocess
.STDOUT
)
143 for port
, proto
in config
.pp
)
144 tunnel_manager
.refresh()
149 nextUpdate
= min(tunnel_manager
.next_refresh
, peer_db
.next_refresh
)
150 if forwarder
!= None:
151 nextUpdate
= min(nextUpdate
, forwarder
.next_refresh
)
152 nextUpdate
= max(0, nextUpdate
- time
.time())
154 ready
, tmp1
, tmp2
= select
.select([read_pipe
], [], [], nextUpdate
)
156 peer_db
.handle_message(read_pipe
.readline())
157 if time
.time() >= peer_db
.next_refresh
:
159 if time
.time() >= tunnel_manager
.next_refresh
:
160 tunnel_manager
.refresh()
161 except KeyboardInterrupt:
164 if __name__
== "__main__":