Commit 6408b7e1 authored by Julien Muchembled's avatar Julien Muchembled Committed by Joanne Hugé

re6st protocol 8: redistribute default route with src prefix

This fixes default packet redirection when merging multiple re6st
networks. Nodes will then install multiple default routes for each re6st
network with the correspond src-prefix.

The changes include:

- redistribute default route with src prefix on gateways
- remove the now obsolete default option
- if subtrees is not available in the kernel, delete src prefix from
  the default route and don't advertise the default route to other
  nodes
- if there is no src prefix in the redistributed default route, add
  one to be retro-compatible with the old gateway behaviour
parent 5d05c34b
#!/usr/bin/python2
import atexit, errno, logging, os, shutil, signal
import socket, struct, subprocess, sys, time, threading
import socket, struct, subprocess, sys
from collections import deque
from functools import partial
if 're6st' not in sys.modules:
......@@ -75,12 +75,9 @@ def getConfig():
_('-B', dest='babel_args', metavar='ARG', action='append', default=[],
help="Extra arguments to forward to Babel.")
_('-D', '--default', action='store_true',
help="Access internet via this network (in this case, make sure you"
" don't already have a default route), or if your kernel was"
" compiled without support for source address based routing"
" (CONFIG_IPV6_SUBTREES). Meaningless with --gateway.")
help="This is an obsolete option and ignored.")
_('--table', type=int, choices=(0,),
help="DEPRECATED: Use --default instead of --table=0")
help="This is an obsolete option and ignored.")
_('--gateway', action='store_true',
help="Act as a gateway for this network (the default route will be"
" exported). Do never use it if you don't know what it means.")
......@@ -159,20 +156,28 @@ def main():
if config.max_clients is None:
config.max_clients = cache.max_clients
if config.table is not None:
logging.warning("--table option is deprecated: use --default instead")
config.default = True
if config.default and config.gateway:
sys.exit("error: conflicting options --default and --gateway")
if config.disable_proto is None:
config.disable_proto = DEFAULT_DISABLED_PROTO
elif 'none' in config.disable_proto:
config.disable_proto = ()
if config.default:
x = ['ip', '-6', 'route', 'add', 'unreachable', '::/128', 'from', '::/128']
has_ipv6_subtrees = not subprocess.call(x)
if has_ipv6_subtrees:
x[3] = 'del'
subprocess.check_call(x)
else:
logging.warning(
"Source address based routing is not enabled in your kernel"
" (CONFIG_IPV6_SUBTREES). %s",
"Assuming you don't merge several re6st networks so routes from"
" other networks will be ignored." if config.gateway else
"This node won't receive traffic to be routed to the internet."
" Make sure you don't already have a default route.")
# Make sure we won't tunnel over re6st.
config.disable_proto = tuple({'tcp6', 'udp6'}.union(
config.disable_proto))
def add_tunnels(iface_list):
for iface in iface_list:
config.babel_args += '-C', 'interface %s type tunnel' % iface
......@@ -376,47 +381,12 @@ def main():
subprocess.call(if_rt)
if_rt[4] = my_subnet
cleanup.append(lambda: subprocess.call(if_rt))
if config.default:
def check_no_default_route():
for route in call(('ip', '-6', 'route', 'show',
'default')).splitlines():
if not (' proto babel ' in route
or ' proto 42 ' in route):
sys.exit("Detected default route (%s)"
" whereas you specified --default."
" Fix your configuration." % route)
check_no_default_route()
def check_no_default_route_thread():
try:
while True:
time.sleep(60)
try:
check_no_default_route()
except OSError, e:
if e.errno != errno.ENOMEM:
raise
except:
utils.log_exception()
finally:
exit.kill_main(1)
t = threading.Thread(target=check_no_default_route_thread)
t.daemon = True
t.start()
else:
x = ['ip', '-6', 'route', 'add',
'unreachable', '::/128', 'from', '::/128']
if subprocess.call(x):
sys.exit('error: Source address based routing is not'
' enabled in your kernel (CONFIG_IPV6_SUBTREES).'
' Try with the --default option.')
x[3] = 'del'
subprocess.check_call(x)
ip('route', 'unreachable', my_network)
config.babel_args += config.iface_list
cleanup.append(plib.router((my_ip, len(subnet)), ipv4,
my_network if config.gateway or config.default else None,
config.gateway, cache.hello,
(my_network, config.gateway, has_ipv6_subtrees),
cache.hello,
os.path.join(config.log, 'babeld.log'),
os.path.join(config.state, 'babeld.state'),
os.path.join(config.run, 'babeld.pid'),
......
......@@ -62,8 +62,10 @@ def client(iface, address_list, encrypt, *args, **kw):
return openvpn(iface, encrypt, *remote, **kw)
def router(ip, ip4, src, gateway, hello_interval, log_path, state_path, pidfile,
def router(ip, ip4, rt6, hello_interval, log_path, state_path, pidfile,
control_socket, default, hmac, *args, **kw):
network, gateway, has_ipv6_subtrees = rt6
network_mask = int(network[network.index('/')+1:])
ip, n = ip
hmac_sign, hmac_accept = hmac
if ip4:
......@@ -75,12 +77,6 @@ def router(ip, ip4, src, gateway, hello_interval, log_path, state_path, pidfile,
'-S', state_path,
'-I', pidfile,
'-s',
# Force use of ipv6 subtrees because:
# - even Linux 2.6.32 has them
# - the fallback implementation using a separate table
# is not equivalent, at least not the way we use babeld
# (and we don't need RTA_SRC for ipv4).
'-C', 'ipv6-subtrees true',
'-C', 'redistribute local deny',
'-C', 'redistribute ip %s/%s eq %s' % (ip, n, n)]
if hmac_sign:
......@@ -97,13 +93,37 @@ def router(ip, ip4, src, gateway, hello_interval, log_path, state_path, pidfile,
cmd += '-C', 'default ' + default
if ip4:
cmd += '-C', 'redistribute ip %s/%s eq %s' % (ip4, n4, n4)
if src:
if gateway:
cmd += '-C', 'redistribute ip ::/0 eq 0 src-prefix ' + src
else:
cmd += '-C', 'install ip ::/0 eq 0 src-prefix ' + src + ' pref-src ' + ip
if gateway:
cmd += '-C', 'redistribute ip ::/0 eq 0 src-prefix ' + network
if not has_ipv6_subtrees:
cmd += (
'-C', 'in ip %s ge %s' % (network, network_mask),
'-C', 'in ip ::/0 deny',
)
elif has_ipv6_subtrees:
# For backward compatibility, if the default route comes from old
# version (without source-prefix).
cmd += (
'-C', 'install ip ::/0 eq 0 src-ip ::/0 src-eq 0 src-prefix ' + network,
)
else:
# We patch babeld:
# - ipv6-subtrees is always true by default
# - if false, source prefix is cleared when the route is installed
cmd += (
'-C', 'ipv6-subtrees false',
# Accept default route from our network.
'-C', 'in ip ::/0 eq 0 src-ip %s src-eq %s' % (network, network_mask),
# Ignore default route from other networks. For backward
# compatibility we accept default routes from old version
# (without source-prefix).
'-C', 'in ip ::/0 eq 0 src-ip ::/0 src-ge 1 deny',
# Tell neighbours not to route to the internet via us,
# because we could be a black hole in case of misconfiguration.
'-C', 'out ip ::/0 eq 0 deny',
)
cmd += ('-C', 'redistribute deny',
'-C', 'install ip ::/0 ge 1 pref-src ' + ip)
'-C', 'install pref-src ' + ip)
if ip4:
cmd += '-C', 'install pref-src ' + ip4
if control_socket:
......
......@@ -32,7 +32,7 @@ if dirty:
# they are intended to the network admin.
# Only 'protocol' is important and it must be increased whenever they would be
# a wish to force an update of nodes.
protocol = 7
protocol = 8
min_protocol = 1
if __name__ == "__main__":
......
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