Commit 031c5e34 authored by Julien Muchembled's avatar Julien Muchembled

Add support for OpenVPN tunnels over IPv6

parent f5b794e8
#!/usr/bin/python -S
import os, sys
if os.environ['script_type'] == 'client-connect':
script_type = os.environ['script_type']
external_ip = lambda: os.getenv('trusted_ip') or os.environ['trusted_ip6']
if script_type == 'client-connect':
# Send client its external ip address
with open(sys.argv[2], 'w') as f:
f.write('push "setenv-safe external_ip %s"\n'
% os.environ['trusted_ip'])
f.write('push "setenv-safe external_ip %s"\n' % external_ip())
# Write into pipe connect/disconnect events
arg1 = sys.argv[1]
if arg1 != 'None':
os.write(int(arg1), '%(script_type)s %(common_name)s %(trusted_ip)s\n'
% os.environ)
os.write(int(arg1), '%s %s %s\n' % (
script_type, os.environ['common_name'], external_ip()))
......@@ -35,7 +35,7 @@ def server(iface, max_clients, dh_path, pipe_fd, port, proto, encrypt, *args, **
'--dh', dh_path,
'--max-clients', str(max_clients),
'--port', str(port),
'--proto', 'tcp-server' if proto == 'tcp' else proto,
'--proto', proto + '-server' if proto in ('tcp', 'tcp6') else proto,
*args, **kw)
......@@ -43,7 +43,7 @@ def client(iface, address_list, encrypt, *args, **kw):
remote = ['--nobind', '--client']
for ip, port, proto in address_list:
remote += '--remote', ip, port, \
'tcp-client' if proto == 'tcp' else proto
proto + '-client' if proto in ('tcp', 'tcp6') else proto
remote += args
return openvpn(iface, encrypt, *remote, **kw)
......
import logging, random, socket, subprocess, time
from collections import deque
from collections import defaultdict, deque
from . import plib, utils
PORT = 326
......@@ -120,7 +120,12 @@ class TunnelManager(object):
self._network = network
self._iface_list = iface_list
self._prefix = prefix
self._address = utils.dump_address(address)
address_dict = defaultdict(list)
for family, address in address:
address_dict[family] += address
self._address = dict((family, utils.dump_address(address))
for family, address in address_dict.iteritems()
if address)
self._ip_changed = ip_changed
self._gateway_manager = MultiGatewayManager(remote_gateway) \
if remote_gateway else None
......@@ -408,7 +413,9 @@ class TunnelManager(object):
except KeyError:
pass
if self._ip_changed:
self._address = utils.dump_address(self._ip_changed(ip))
family, address = self._ip_changed(ip)
if address:
self._address[family] = utils.dump_address(address)
def handlePeerEvent(self):
msg, address = self.sock.recvfrom(1<<16)
......@@ -440,7 +447,8 @@ class TunnelManager(object):
self._makeTunnel(prefix, address)
elif code == 2: # request
if self._address:
msg = '\1%s %s\n' % (self._prefix, self._address)
msg = '\1%s %s\n' % (self._prefix,
';'.join(self._address.itervalues()))
try:
self.sock.sendto(msg, address[:2])
except socket.error, e:
......
from functools import wraps
import logging, socket, time
import miniupnpc
import logging
import time
class UPnPException(Exception):
......@@ -33,10 +32,10 @@ class Forwarder(object):
if not ip:
ip = self.refresh()
if not ip:
return ()
return socket.AF_INET, ()
# If port is None, we assume we're not NATed.
return [(ip, str(port or local), proto)
for local, proto, port in self._rules]
return socket.AF_INET, [(ip, str(port or local), proto)
for local, proto, port in self._rules]
def addRule(self, local_port, proto):
self._rules.append([local_port, proto, None])
......
#!/usr/bin/python
import atexit, errno, logging, os, select, signal
import atexit, errno, logging, os, select, signal, socket
import sqlite3, subprocess, sys, time, threading
from collections import deque
from OpenSSL import crypto
......@@ -84,7 +84,7 @@ def getConfig():
help='Specify that tunnels should be encrypted.')
_('--pp', nargs=2, action='append', metavar=('PORT', 'PROTO'),
help="Port and protocol to be announced to other peers, ordered by"
" preference. For each protocol (either udp or tcp), start one"
" preference. For each protocol (udp, tcp, udp6, tcp6), start one"
" openvpn server on the first given port."
" (default: --pp 1194 udp --pp 1194 tcp)")
_('--dh',
......@@ -108,8 +108,8 @@ def getConfig():
_('--remote-gateway', action='append', dest='gw_list',
help="Force each tunnel to be created through one the given gateways,"
" in a round-robin fashion.")
_('--disable-proto', action='append', choices=('none', 'udp', 'tcp'),
default=['udp'],
_('--disable-proto', action='append',
choices=('none', 'udp', 'tcp', 'udp6', 'tcp6'), default=['udp', 'udp6'],
help="Do never try to create tunnels using given protocols."
" 'none' has precedence over other options.")
_('--client', metavar='HOST,PORT,PROTO[;...]',
......@@ -195,7 +195,11 @@ def main():
if 'none' in config.disable_proto:
config.disable_proto = ()
address = []
if not config.table:
# Make sure we won't tunnel over re6st.
config.disable_proto = tuple(set(('tcp6', 'udp6')).union(
config.disable_proto))
address = ()
server_tunnels = {}
forwarder = None
if config.client:
......@@ -210,7 +214,18 @@ def main():
else:
pp = [x for x in ((1194, 'udp'), (1194, 'tcp'))
if x[1] not in config.disable_proto]
ip_changed = lambda ip: [(ip, str(port), proto) for port, proto in pp]
def ip_changed(ip):
for family, proto_list in ((socket.AF_INET, ('tcp', 'udp')),
(socket.AF_INET6, ('tcp6', 'udp6'))):
try:
socket.inet_pton(family, ip)
break
except socket.error:
pass
else:
family = None
return family, [(ip, str(port), proto) for port, proto in pp
if not family or proto in proto_list]
if config.gw_list:
gw_list = deque(config.gw_list)
def remote_gateway(dest):
......@@ -241,9 +256,9 @@ def main():
for port, proto in pp:
forwarder.addRule(port, proto)
ip_changed = forwarder.checkExternalIp
address = ip_changed()
address = ip_changed(),
elif 'any' not in config.ip:
address = sum(map(ip_changed, config.ip), [])
address = map(ip_changed, config.ip)
ip_changed = None
for x in pp:
server_tunnels.setdefault('re6stnet-' + x[1], x)
......
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