Commit 9826a58c authored by Ulysse Beaugnon's avatar Ulysse Beaugnon

Rename vifibnet to re6stnet

Check for dead tunnels evry 5 seconds instead of waiting for the next tunnel_refresh
parent 9b865d79
Vifibnet is a daemon setting up a resilient virtual private network over the
re6stnet is a daemon setting up a resilient virtual private network over the
internet
HOW TO:
Vifibnet ( sic ) has three separate components : a setup (setup.py), a
server (registry.py) and a client (vifibnet.py.
re6stnet ( sic ) has three separate components : a setup (setup.py), a
server (registry.py) and a client (re6stnet.py.
Lambda users only have to launch the setup and then their client.
The server is meant to be started once on a node which also will be running
a client instance.
......@@ -27,7 +27,7 @@ OPTIONS : REGISTRY.PY
The port on which the server will listen
--private ip
Ipv6 address of the vifibnet client running on the machine. This
Ipv6 address of the re6stnet client running on the machine. This
address will be advertised only to nodes having a valid
certificate.
......@@ -62,18 +62,18 @@ OPTIONS : REGISTRY.PY
OPTIONS : SETUP.PY
usage : ./setup [options...]
--server address
Ip address of the machine running the vifibnet server. Both ipv4
Ip address of the machine running the re6stnet server. Both ipv4
and ipv6 addresses are supported.
--port port
Port to connect to on the machine running the vifibnet server.
Port to connect to on the machine running the re6stnet server.
-d, --dir directory
Path of a directory where will be stored the files generated by the
setup. The Setup genereates the following files, in the explicit
order :
- ca.pem : certificate authority file downloaded from the server
- peers.db : peers database initialized for vifibnet.py
- peers.db : peers database initialized for re6stnet.py
- cert.key : private key generated by the script
- cert.crt : individual certificate file generated by the server
- dh2048.pem : dh file for oenvpn server
......@@ -99,8 +99,8 @@ OPTIONS : SETUP.PY
not have any, an execption will occur, and the script will stop
OPTIONS : VIFIBNET.PY
usage : ./vifibnet.py [options...]
OPTIONS : RES6NET.PY
usage : ./re6stnet.py [options...]
--ip address port proto
Specify connection information to be advertised to other nodes.
address MUST be a ipv4 address since as of now openvpn does not
......@@ -124,11 +124,11 @@ OPTIONS : VIFIBNET.PY
-s, --state directory
Path to the directory used for state files. State files include :
- peers.db : the peers db used to establish connection
- vifibnet.babeld.state : babeld state file ( created if does not
- re6stnet.babeld.state : babeld state file ( created if does not
exists, overriden if exists )
There must be a valid peers db file ( named peers.db ) in the
directory. A valid peers db file can be created with setup.py
Default : /var/lib/vifibnet
Default : /var/lib/re6stnet
-v, --verbose level
Defines the verbose level, level should be an integer between 0
......@@ -165,7 +165,7 @@ OPTIONS : VIFIBNET.PY
Port and protocol used by the openvpn server(s). Start one openvpn
server for each couple port/protocol specified.
Additionally, if no external configuration is given in the command
line, vifibnet will attempt to forward a port with upnp for each
line, re6stnet will attempt to forward a port with upnp for each
couple port/proto given.
Protocols should be either udp or tcp-server.
Default : (1194, udp), (1194, tcp-server)
......@@ -188,12 +188,12 @@ OPTIONS : VIFIBNET.PY
(for more information see the openvpn man page)
--ca path
Path to the certificate authority file delivered by the vifibnet
Path to the certificate authority file delivered by the re6stnet
server. The prefix of the VPN network is included in the serial
number of the file.
--cert path
Path to the individual certificate file delivered by the vifibnet
Path to the individual certificate file delivered by the re6stnet
server. The prefix of the machine is included in the certificate's
subject common name.
......@@ -210,15 +210,15 @@ OPTIONS : VIFIBNET.PY
openvpn_args
Additional arguments to be passed down to all openvpn processes
can be given at the end of the command line.
In that case, insert '--' to delimit vifibnet regular options
In that case, insert '--' to delimit re6stnet regular options
from the additional openvpn arguments. The list of arguments will
be passed down to ALL openvpn processes ( including servers )
exactly as they are given
One SHOULD give a --key argument with the key file delivered by the
vifibnet server
re6stnet server
@file
You can give to vifibnet a config file as a regular argument
You can give to re6stnet a config file as a regular argument
(meaning before giving optional openvpn arguments)
The file should contain one option per line, possibly ommitting
the '--'. Only long option are allowed (i.e "v 3" will not work
......@@ -246,7 +246,7 @@ BaseHTTPServer.BaseHTTPRequestHandler.address_string = not_insane_address_string
New log system :
we use the logging module now. There are three levels for log messages :
- info : give basic information about what vifibnet is doing
- info : give basic information about what re6stnet is doing
- debug : display internal work of the script (finished action, detailed
information about tunnels, etc... )
- trace : for intensive debug, display configuration, arguments given to
......
#!/usr/bin/python -S
import os, sys
import os
import sys
# example of os.environ
{'X509_0_C': 'FR',
......@@ -15,7 +16,7 @@ import os, sys
'daemon_log_redirect': '0',
'daemon_pid': '11637',
'daemon_start_time': '1341568405',
'dev': 'vifibnet',
'dev': 're6stnet',
'link_mtu': '1573',
'local_port_1': '1194',
'proto_1': 'udp',
......
......@@ -44,9 +44,9 @@ def getConfig():
_('--peers-db-refresh', default=3600, type=int,
help='the time (seconds) to wait before refreshing the peers db')
_('-l', '--log', default='/var/log',
help='Path to vifibnet logs directory')
_('-s', '--state', default='/var/lib/vifibnet',
help='Path to vifibnet state directory')
help='Path to re6stnet logs directory')
_('-s', '--state', default='/var/lib/re6stnet',
help='Path to re6stnet state directory')
_('-v', '--verbose', default=0, type=int,
help='Defines the verbose level')
_('-i', '--interface', action='append', dest='iface_list', default=[],
......@@ -72,11 +72,10 @@ def getConfig():
help='Path to the certificate file')
_('--key', required=True,
help='Path to the private key file')
# args to be removed ?
_('--connection-count', default=20, type=int,
help='Number of tunnels')
_('--refresh-ratio', default=0.05, type=float,
help='''The ratio of connections to drop when refreshing the
_('--refresh-count', default=1, type=int,
help='''The number of connections to drop when refreshing the
connections''')
# Openvpn options
_('openvpn_args', nargs=argparse.REMAINDER,
......@@ -89,7 +88,7 @@ def main():
config = getConfig()
if not config.pp:
config.pp = [['1194', 'udp'], ['1194', 'tcp-server']]
config.pp = list((port, proto, 'vifibnet-%s' % proto)
config.pp = list((port, proto, 're6stnet-%s' % proto)
for port, proto in config.pp)
manual = bool(config.address)
network = utils.networkFromCa(config.ca)
......@@ -120,10 +119,10 @@ def main():
for c, s in ('udp', 'udp'), ('tcp-client', 'tcp-server'):
if len(list(x for x in config.address if x[2] == c)) \
< len(list(x for x in config.pp if x[1] == s)):
logging.warning("""Beware: in manual configuration, you
declared less external configurations regarding
protocol %s/%s than you gave internal server
configurations""" % (c, s))
logging.warning("""Beware: in manual configuration, you
declared less external configurations regarding
protocol %s/%s than you gave internal server
configurations""" % (c, s))
else:
logging.info('Attempting automatic configuration via UPnP...')
try:
......@@ -141,7 +140,7 @@ def main():
manual, config.pp, 200)
tunnel_manager = tunnel.TunnelManager(write_pipe, peer_db, openvpn_args,
config.hello, config.tunnel_refresh, config.connection_count,
config.refresh_ratio, config.iface_list, network)
config.refresh_count, config.iface_list, network)
# Launch routing protocol. WARNING : you have to be root to start babeld
interface_list = list(tunnel_manager.free_interface_set) \
......@@ -157,7 +156,7 @@ def main():
config.connection_count, config.dh, write_pipe, port,
proto, config.hello, '--dev', iface, *openvpn_args,
stdout=os.open(os.path.join(config.log,
'vifibnet.server.%s.log' % (proto,)),
're6stnet.server.%s.log' % (proto,)),
os.O_WRONLY | os.O_CREAT | os.O_TRUNC),
stderr=subprocess.STDOUT)
for port, proto, iface in config.pp)
......
......@@ -45,7 +45,7 @@ class main(object):
# Command line parsing
parser = argparse.ArgumentParser(
description='Peer discovery http server for vifibnet')
description='Peer discovery http server for re6stnet')
_ = parser.add_argument
_('port', type=int, help='Port of the host server')
_('--db', required=True,
......@@ -125,9 +125,9 @@ class main(object):
# Creating and sending email
s = smtplib.SMTP(self.config.mailhost)
me = 'postmaster@vifibnet.com'
msg = MIMEText('Hello world !\nYour token : %s' % (token,)) # XXX
msg['Subject'] = '[Vifibnet] Token Request'
me = 'postmaster@re6st.net'
msg = MIMEText('Hello world !\nYour token : %s' % (token,)) # XXX
msg['Subject'] = '[re6stnet] Token Request'
msg['From'] = me
msg['To'] = email
s.sendmail(me, email, msg.as_string())
......@@ -158,7 +158,7 @@ class main(object):
try:
token, email, prefix_len, _ = self.db.execute("SELECT * FROM tokens WHERE token = ?", (token,)).next()
except StopIteration:
logging.exception('Bad token (%s) in request' %(token,))
logging.exception('Bad token (%s) in request' % (token,))
raise
self.db.execute("DELETE FROM tokens WHERE token = ?", (token,))
......
......@@ -4,7 +4,7 @@ from OpenSSL import crypto
def main():
parser = argparse.ArgumentParser(
description='Setup script for vifib')
description='Setup script for re6stnet')
_ = parser.add_argument
_('--ca-only', action='store_true',
help='To only get CA form server')
......@@ -12,7 +12,7 @@ def main():
help='Address of the server delivering certifiactes')
_('--port', required=True, type=int,
help='Port to which connect on the server')
_('-d', '--dir', default='/etc/vifib',
_('-d', '--dir', default='/etc/re6stnet',
help='Directory where the key and certificate will be stored')
_('-r', '--req', nargs=2, action='append',
help='Name and value of certificate request additional arguments')
......@@ -63,7 +63,7 @@ def main():
# Generating dh file
if not os.access(os.path.join(config.dir, 'dh2048.pem'), os.F_OK):
subprocess.call(['openssl', 'dhparam', '-out', os.path.join(config.dir, 'dh2048.pem'), '2048'])
subprocess.call(['openssl', 'dhparam', '-out', os.path.join(config.dir, 'dh2048.pem'), '2048'])
print "Certificate setup complete."
......
......@@ -112,7 +112,7 @@ void Graph::GetRoutesFrom(int from, int* nRoutes, int* prevs, int* distances)
}
void Graph::UpdateLowRoutes(double& avgDistance, double unreachable, double* arityDistrib)
void Graph::UpdateLowRoutes(double& avgDistance, double unreachable, double* arityDistrib, int refreshCount)
{
routesResult results[size];
......@@ -154,23 +154,16 @@ void Graph::UpdateLowRoutes(double& avgDistance, double unreachable, double* ari
for(int i = 0; i<size; i++)
{
//cout << "["; cout.flush();
routesResult r = results[i];
if(r.toDelete >= 0)
RemoveEdge(i, r.toDelete);
//cout << "#"; cout.flush();
SaturateNode(i);
//cout << "]"; cout.flush();
avgDistance += r.avgDistance*(size-r.unreachable);
avgDistanceWeight += size-r.unreachable;
unreachable += r.unreachable;
arityDistrib[adjacency[i].size()]++;
}
avgDistance /= avgDistanceWeight;
......
// To compile : g++ -std=c++0x latency.cpp graph.cpp main.cpp -lpthread
// The best distance : 66.9239 with a full graph
// other dataset : http://pdos.csail.mit.edu/p2psim/kingdata/
#include "main.h"
......
......@@ -15,7 +15,7 @@ class Connection:
ovpn_args):
self.process = plib.client(address, write_pipe, hello, '--dev', iface,
*ovpn_args, stdout=os.open(os.path.join(log,
'vifibnet.client.%s.log' % (prefix,)),
're6stnet.client.%s.log' % (prefix,)),
os.O_WRONLY | os.O_CREAT | os.O_TRUNC),
stderr=subprocess.STDOUT)
......@@ -71,7 +71,7 @@ class Connection:
class TunnelManager:
def __init__(self, write_pipe, peer_db, openvpn_args, hello_interval,
refresh, connection_count, refresh_ratio, iface_list, network):
refresh, connection_count, refresh_count, iface_list, network):
self._write_pipe = write_pipe
self._peer_db = peer_db
self._connection_dict = {}
......@@ -82,21 +82,25 @@ class TunnelManager:
self._network = network
self._net_len = len(network)
self._iface_list = iface_list
self.next_refresh = time.time()
self._next_tunnel_refresh = time.time()
self._client_count = (connection_count + 1) // 2
self._refresh_count = int(math.ceil(refresh_ratio * self._client_count))
self._refresh_count = refresh_count
self.free_interface_set = set('client' + str(i)
for i in xrange(1, self._client_count + 1))
def refresh(self):
logging.info('Refreshing the tunnels...')
self._cleanDeads()
self._countRoutes()
self._removeSomeTunnels()
if self._next_tunnel_refresh < time.time():
self._countRoutes()
self._removeSomeTunnels()
self._next_tunnel_refresh = time.time() + self._refresh_time
self._makeNewTunnels()
logging.debug('Tunnels refreshed')
self.next_refresh = time.time() + self._refresh_time
self.next_refresh = time.time() + 5
def _cleanDeads(self):
for prefix in self._connection_dict.keys():
......@@ -117,7 +121,7 @@ class TunnelManager:
def _kill(self, prefix):
logging.info('Killing the connection with %s/%u...'
% (hex(int(prefix,2))[2:], len(prefix)))
% (hex(int(prefix, 2))[2:], len(prefix)))
connection = self._connection_dict.pop(prefix)
try:
connection.process.terminate()
......@@ -128,7 +132,7 @@ class TunnelManager:
self._peer_db.unusePeer(prefix)
del self._iface_to_prefix[connection.iface]
logging.trace('Connection with %s/%u killed'
% (hex(int(prefix,2))[2:], len(prefix)))
% (hex(int(prefix, 2))[2:], len(prefix)))
def _makeNewTunnels(self):
i = 0
......@@ -184,4 +188,3 @@ class TunnelManager:
def killAll(self):
for prefix in self._connection_dict.keys():
self._kill(prefix)
import miniupnpc
import logging
import time
import utils
class NoUPnPDevice(Exception):
......@@ -45,7 +45,7 @@ class Forwarder:
# Make the redirection
if self._u.addportmapping(external_port, 'UDP', self._u.lanaddr,
int(local_port), 'Vifib openvpn server', ''):
int(local_port), 're6stnet openvpn server', ''):
logging.debug('Forwarding %s:%s to %s:%s' % (self._external_ip,
external_port, self._u.lanaddr, local_port))
self._rules.append((external_port, int(local_port), upnp_proto))
......@@ -55,5 +55,5 @@ class Forwarder:
logging.debug('Refreshing port forwarding')
for external_port, local_port, proto in self._rules:
self._u.addportmapping(external_port, proto, self._u.lanaddr,
local_port, 'Vifib openvpn server', '')
local_port, 're6stnet openvpn server', '')
self.next_refresh = time.time() + 3600
......@@ -3,6 +3,7 @@ from OpenSSL import crypto
logging_levels = logging.WARNING, logging.INFO, logging.DEBUG, 5
def setupLog(log_level):
logging.basicConfig(level=logging_levels[log_level],
format='%(asctime)s : %(message)s',
......@@ -10,28 +11,33 @@ def setupLog(log_level):
logging.addLevelName(5, 'TRACE')
logging.trace = lambda *args, **kw: logging.log(5, *args, **kw)
def binFromIp(ip):
ip1, ip2 = struct.unpack('>QQ', socket.inet_pton(socket.AF_INET6, ip))
return bin(ip1)[2:].rjust(64, '0') + bin(ip2)[2:].rjust(64, '0')
def ipFromBin(prefix):
prefix = hex(int(prefix, 2))[2:]
ip = ''
for i in xrange(0, len(prefix) - 1, 4):
ip += prefix[i:i+4] + ':'
ip += prefix[i:i + 4] + ':'
return ip.rstrip(':')
def ipFromPrefix(vifibnet, prefix, prefix_len):
def ipFromPrefix(re6stnet, prefix, prefix_len):
prefix = bin(int(prefix))[2:].rjust(prefix_len, '0')
ip_t = (vifibnet + prefix).ljust(127, '0').ljust(128, '1')
ip_t = (re6stnet + prefix).ljust(127, '0').ljust(128, '1')
return ipFromBin(ip_t), prefix
def networkFromCa(ca_path):
# Get network prefix from ca.crt
with open(ca_path, 'r') as f:
ca = crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
return bin(ca.get_serial_number())[3:]
def ipFromCert(network, cert_path):
# Get ip from cert.crt
with open(cert_path, 'r') as f:
......@@ -40,9 +46,11 @@ def ipFromCert(network, cert_path):
prefix, prefix_len = subject.CN.split('/')
return ipFromPrefix(network, prefix, int(prefix_len))
def address_str(address_set):
return ';'.join(map(','.join, address_set))
def address_list(address_list):
return list(tuple(address.split(','))
for address in address_list.split(';'))
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