...
 
Commits (31)
  • Julien Muchembled's avatar
  • Julien Muchembled's avatar
    Bump protocol version · cfb7e3f7
    Julien Muchembled authored
    Commit 6c4a5443 fixes a routing issue and
    as usual, all nodes without exception must either route correctly or die:
    in the future, we may want to force all nodes to upgrade.
    cfb7e3f7
  • Jean-Paul Smets's avatar
    Update README.rst · ca2111f5
    Jean-Paul Smets authored
    ca2111f5
  • Jean-Paul Smets's avatar
    Update README.rst · 8872f742
    Jean-Paul Smets authored
    8872f742
  • Jean-Paul Smets's avatar
    Update README.rst · a0f2ff2a
    Jean-Paul Smets authored
    a0f2ff2a
  • Jean-Paul Smets's avatar
    Update README.rst · 9ab18393
    Jean-Paul Smets authored
    9ab18393
  • Julien Muchembled's avatar
    f3d45f8e
  • Julien Muchembled's avatar
    New --console option · f2363823
    Julien Muchembled authored
    f2363823
  • Julien Muchembled's avatar
    1d82935d
  • Julien Muchembled's avatar
  • Julien Muchembled's avatar
    8e3cc1ea
  • Julien Muchembled's avatar
  • Julien Muchembled's avatar
    demo: enable --console for all nodes · 674cad32
    Julien Muchembled authored
    674cad32
  • Julien Muchembled's avatar
    Experimental support of RINA · 596050eb
    Julien Muchembled authored
    596050eb
  • Julien Muchembled's avatar
    3e1a6244
  • Julien Muchembled's avatar
    rina: recover from cases where normal.DIF is already registered at startup · 128edb83
    Julien Muchembled authored
    Which happens when only re6stnet is restarted. The DIF must even be recreated
    if the local certificate has changed, so that we can reconfigure the shim DIF.
    128edb83
  • Julien Muchembled's avatar
    6569cf1e
  • Julien Muchembled's avatar
  • Julien Muchembled's avatar
    Document how to pronunce're6st' · 4e9332f9
    Julien Muchembled authored
    4e9332f9
  • Julien Muchembled's avatar
    README: rephrasing · d59d6575
    Julien Muchembled authored
    d59d6575
  • Julien Muchembled's avatar
    Update TODO · e92ca586
    Julien Muchembled authored
    e92ca586
  • Julien Muchembled's avatar
    registry: new @rpc_private decorator · 96104548
    Julien Muchembled authored
    96104548
  • Rafael Monnerat's avatar
    Move iterRoutes helper from draft/ to re6st.ctl module · 834959b9
    Rafael Monnerat authored
    This is a useful class that can be used for other reasons.
    834959b9
  • Rafael Monnerat's avatar
    registry: Add API for add/delete/is a specific Token · 10f22751
    Rafael Monnerat authored
        addToken, isToken and DeleteToken are introduced to manage tokens created
        by other system (like SlapOS for example).
    
    If token is present, raise conflict instead loop until timeout.
    10f22751
  • Rafael Monnerat's avatar
    registry: add some IPv4/IPv6 helper API · 5a377d05
    Rafael Monnerat authored
    With this API, a client can query IPv6/IPv4 information outside re6stnet/babel
    for reporting.
    
    The API considers that the email is unique, else it returns the first
    occurrence. For SlapOS integration, it is more than enough to consider
    that email will not be repeated.
    5a377d05
  • Rafael Monnerat's avatar
    registry: new --authorized-origin option · 0ed6077d
    Rafael Monnerat authored
    The list of authorized IPs for private RPCs is now configurable.
    This is required when the registry is not bound to localhost.
    0ed6077d
  • Julien Muchembled's avatar
  • Julien Muchembled's avatar
  • Julien Muchembled's avatar
    Lower again MTU for UDPv4 tunnels · 8a1c74d0
    Julien Muchembled authored
    8a1c74d0
  • Julien Muchembled's avatar
  • Kirill Smelkov's avatar
    daemon: Force NetworkManager on Debian 8 to ignore restnet* interfaces · aa57ff4c
    Kirill Smelkov authored
    A problem was discovered on several production machines of a project
    installed by client with Debian 8.9 with eth0 being managed by
    NetworkManager (to get IP via DHCP):
    
    Even though re6stnet was starting ok, it was either failing completely
    to bring any of its interfaces up, or was loosing brought up interfaces
    very fast. Symptoms were:
    
    - openvpn links are broken after 60s (we use `--ping-exit 60` on both
      openvpn ends)
    
    - I forced links to stay alive with `O--ping O10`
    
    - I increased babel debug level `B-d B1`
    
    - it indeed shows babel does not send hello
    
    in despite openvpns running interfaces itself become down:
    
        root@...:/etc/re6stnet# ip link |grep re6st
        145: re6stnet-tcp: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 100
        146: re6stnet1: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 100
        147: re6stnet2: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 100
        148: re6stnet3: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 100
        149: re6stnet4: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 100
        150: re6stnet5: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 100
        151: re6stnet6: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 100
        152: re6stnet7: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 100
        153: re6stnet8: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 100
        154: re6stnet9: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 100
        155: re6stnet10: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 100
    
    nmcli says networkmanager does not manage it:
    
        root@...:/etc/re6stnet# nmcli d
        DEVICE        TYPE      STATE      CONNECTION
        eth0          ethernet  connected  Wired connection 1
        lo            loopback  unmanaged  --
        re6stnet-tcp  tap       unmanaged  --
        re6stnet1     tap       unmanaged  --
        re6stnet10    tap       unmanaged  --
        re6stnet2     tap       unmanaged  --
        re6stnet3     tap       unmanaged  --
        re6stnet4     tap       unmanaged  --
        re6stnet5     tap       unmanaged  --
        re6stnet6     tap       unmanaged  --
        re6stnet7     tap       unmanaged  --
        re6stnet8     tap       unmanaged  --
        re6stnet9     tap       unmanaged  --
    
    however I see a lot of churn about re6stnetX in NM logs, e.g.
    
        <info> (re6stnet6): found matching connection 're6stnet6'
        <info> (re6stnet6): device state change: unmanaged -> unavailable (reason 'connection-assumed') [10 20 41]
        <info> (re6stnet6): device state change: unavailable -> disconnected (reason 'connection-assumed') [20 30 41]
        <info> Activation (re6stnet6) starting connection 're6stnet6'
        <info> Activation (re6stnet6) Stage 1 of 5 (Device Prepare) scheduled...
        <info> Activation (re6stnet6) Stage 1 of 5 (Device Prepare) started...
        <info> (re6stnet6): device state change: disconnected -> prepare (reason 'none') [30 40 0]
        <info> Activation (re6stnet6) Stage 2 of 5 (Device Configure) scheduled...
        <info> Activation (re6stnet6) Stage 1 of 5 (Device Prepare) complete.
        <info> Activation (re6stnet6) Stage 2 of 5 (Device Configure) starting...
        <info> (re6stnet6): device state change: prepare -> config (reason 'none') [40 50 0]
        <info> Activation (re6stnet6) Stage 2 of 5 (Device Configure) successful.
        <info> Activation (re6stnet6) Stage 3 of 5 (IP Configure Start) scheduled.
        <info> Activation (re6stnet6) Stage 2 of 5 (Device Configure) complete.
        <info> Activation (re6stnet6) Stage 3 of 5 (IP Configure Start) started...
        <info> (re6stnet6): device state change: config -> ip-config (reason 'none') [50 70 0]
        <info> (re6stnet6): device state change: ip-config -> failed (reason 'ip-config-unavailable') [70 120 5]
        <info> Disabling autoconnect for connection 're6stnet6'.
        <warn> Activation (re6stnet6) failed for connection 're6stnet6'
        <info> Activation (re6stnet6) Stage 3 of 5 (IP Configure Start) complete.
        <info> (re6stnet6): device state change: failed -> disconnected (reason 'none') [120 30 0]
        <info> (re6stnet6): deactivating device (reason 'none') [0]
        <info> (re6stnet6): device state change: disconnected -> unmanaged (reason 'none') [30 10 0]
        <info> (re6stnet6): link disconnected
    
    as the result re6stnet does not work
    
        root@...:/etc/re6stnet# ip -6 r
        unreachable 2001:67c:1254:e:70::/80 dev lo  proto kernel  metric 256  error -101
        unreachable 2001:67c:1254::/48 dev lo  metric 1024  error -101
        fe80::/64 dev eth0  proto kernel  metric 256
    
    On a couple of other machines I see similar symptoms but with e.g. only 1
    re6stnet interface staying up and thus "re6stnet working" but if it goes down
    it will become all down.
    
    Julien suggested it is really NetworkManager who messes things up and advised to
    put `iface re6stnetX inet manual` lines into /etc/network/interfaces and that
    worked - re6stnetX interfaces were no longer brought down and IPv6 started to
    work everywhere.
    
    So let's do this kind of setup by default, so that next poor soul does not need
    to debug that whole conscious old NetworkManager from Debian 8 `nmcli d`
    reporting is not telling the full truth and how to make re6stnet work.
    
    I mean when people install re6st-node package on a Debian 8 box with
    NetworkManager enabled it should be just working out of the box.
    
    P.S. with recent NetworkManager (1.10.2, from current Debian testing)
         re6st-node works out of the box without this patch.
    
    /cc @jm, @rafael, @Tyagov
    aa57ff4c
......@@ -18,6 +18,7 @@ install: install-noinit
install-noinit: install-man
install -Dp daemon/network-manager $(DESTDIR)$(NM)
install -Dpm 0644 daemon/interfaces $(DESTDIR)/etc/network/interfaces.d/re6stnet
set -e $(DESTDIR)$(PREFIX) /bin/re6stnet; [ -x $$1$$2 ] || \
$(or $(PYTHON),python2) setup.py install \
--prefix=$(PREFIX) --root=$(DESTDIR); \
......
......@@ -23,22 +23,24 @@ re6stnet can be used to:
- create large networks
- give ipv6 addresses to machines with only ipv4 available
Building an ipv4 network is also supported if you have software that does not
Building an ipv4 network is also supported if one has software that does not
support ipv6.
How to pronounce `re6st`? Like `resist`.
HOW IT WORKS
============
A re6stnet network consists of at least one server (re6st-registry) and many
nodes (re6stnet). The server is only used to deliver certificates for secure
authentication in establishing tunnels, and to bootstrap new nodes.
authentication of peers, and to bootstrap new nodes.
re6stnet can detect and take into account nodes present on the local network.
Resilience
----------
re6stnet guarantees that if there exists a route between two machines,
traffic will be correctly routed between these two machines.
Even if the registry node is down, the probability that the network isn't
Even if the registry node is down, the probability that the network is not
connected is very low for big enough networks (more than a hundred nodes).
Scalability
......@@ -75,6 +77,18 @@ Installation
| re6stnet is also distributed as a Python egg:
| https://pypi.python.org/pypi/re6stnet
References
==========
| Building a resilient overlay network : Re6stnet
| http://www.j-io.org/P-ViFiB-Resilient.Overlay.Network/Base_download
| GrandeNet - The Internet on Steroids
| https://www.nexedi.com/blog/NXD-Document.Blog.Grandenet.Internet.On.Steroids
| Grandenet success case
| https://www.nexedi.com/success/erp5-GKR.Success.Case
| n-Order Re6st - Achieving Resiliency and Scaliblity
| https://www.nexedi.com/blog/NXD-Document.Blog.N.Order.Res6st.Resiliency.And.Scalability
Usage
=====
......
- Put more information in the token mail (registry), such as:
- We have forked babeld for several changes. We'd like all our patches to be
merged upstream. See https://lab.nexedi.com/nexedi/babeld
- the ip address of the network being built
- the creator of the network ( add option in registry ? )
- Filter non-routable IPs. Add an option not to do it.
- Babel limitations:
- More runtime configuration changes (i.e. without complete restart).
- Babel must be able to set source address on routes it installed. Otherwise,
a wrong IP will be selected if managed interfaces already have several
public IPv6. If there's only one interface like this, a workaround is to
use --main-interface option on it.
- Several subprocesses like babeld are started at the beginning and never
watched, because they should never exit. Their management must be moved to
the main loop, to restart them in case of failure or configuration change.
- Filter non-routable IPs. Add an option not to do it.
- Put more information in the token mail (registry), such as:
- Abort in case of import child process failure (babel, openvpn server,
openvpn client if run with --client).
- the ip address of the network being built
- the creator of the network ( add option in registry ? )
- registry: add '--home PATH' command line option so that / display an HTML
page from PATH (use new str.format for templating)
......
# force NetworkManager to ignore re6stnet interfaces
#
# On Debian 8.9 (NetworkManager 0.9.10.0) even though `nmcli d` says re6stnet*
# interfaces are unmanaged, log shows NetworkManager tries to mess with them
# and frequently brings this interfaces down.
iface re6stnet-tcp inet manual
iface re6stnet1 inet manual
iface re6stnet2 inet manual
iface re6stnet3 inet manual
iface re6stnet4 inet manual
iface re6stnet5 inet manual
iface re6stnet6 inet manual
iface re6stnet7 inet manual
iface re6stnet8 inet manual
iface re6stnet9 inet manual
iface re6stnet10 inet manual
......@@ -8,7 +8,7 @@ X-Python-Version: >= 2.7
Package: re6stnet
Architecture: all
Depends: ${misc:Depends}, python (>= 2.7), python-pkg-resources, python-openssl (>= 0.13), openvpn (>= 2.3), babeld (= 1.6.2-nxd1), iproute2 | iproute, openssl
Depends: ${misc:Depends}, ${python:Depends}, python-pkg-resources, python-openssl (>= 0.13), openvpn (>= 2.3), babeld (= 1.6.2-nxd1), iproute2 | iproute, openssl
Recommends: ${python:Recommends}, logrotate
Suggests: ndisc6
Conflicts: re6st-node
......
......@@ -14,7 +14,8 @@ build-package: debian/changelog
include debian/common.mk
override_dh_python2:
dh_python2 --no-guessing-deps --depends=pyOpenSSL --recommends=miniupnpc
sed -i /^miniupnpc$$/d `find $(TMP)/usr -name requires.txt`
dh_python2 --recommends=miniupnpc
override_dh_auto_clean:
make clean
......
......@@ -211,8 +211,9 @@ if 1:
p.communicate(str(token[0]))
os.remove(dh_path)
os.remove(folder + '/ca.crt')
node.screen('./py re6stnet @%s/re6stnet.conf -v%u --registry %s %s'
% (folder, VERBOSE, registry, args))
node.screen('./py re6stnet @%s/re6stnet.conf -v%u --registry %s'
' --console %s/run/console.sock %s' % (
folder, VERBOSE, registry, folder, args))
re6stnet(registry, 'registry', '--ip ' + REGISTRY, registry='http://localhost/')
re6stnet(machine1, 'm1', '-I%s' % m1_if_0.name)
re6stnet(machine2, 'm2', '--remote-gateway 10.1.1.1', prefix_len=80)
......@@ -325,7 +326,7 @@ if len(sys.argv) > 1:
if page < 2:
body = route_svg(page)
else:
gv = registry.Popen(('python', '-c', r"""if 1:
body = registry.Popen(('python', '-c', r"""if 1:
import math, json
from re6st.registry import RegistryClient
g = json.loads(RegistryClient(
......@@ -349,10 +350,10 @@ if len(sys.argv) > 1:
print '"%s" -> "%s";' % (n, title(v))
print '}'
"""), stdout=subprocess.PIPE, cwd="..").communicate()[0]
if gv:
if body:
body = subprocess.Popen(('neato', '-Tsvg'),
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
).communicate(gv)[0]
).communicate(body)[0]
if not body:
self.send_error(500)
return
......
......@@ -7,26 +7,6 @@ if 're6st' not in sys.modules:
import os; sys.path[0] = os.path.dirname(sys.path[0])
from re6st import ctl, tunnel, utils
class iterRoutes(object):
_waiting = True
def __new__(cls, control_socket, network):
self = object.__new__(cls)
c = ctl.Babel(control_socket, self, network)
c.request_dump()
while self._waiting:
args = {}, {}, ()
c.select(*args)
utils.select(*args)
return (prefix
for neigh_routes in c.neighbours.itervalues()
for prefix in neigh_routes[1]
if prefix)
def babel_dump(self):
self._waiting = False
def cmd_update(db, config):
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
......@@ -36,7 +16,7 @@ def cmd_update(db, config):
p = dict(q("SELECT prefix, mode FROM ip"))
peers = set()
now = int(time.time())
for prefix in iterRoutes(config.control_socket, network):
for prefix in ctl.iterRoutes(config.control_socket, network):
if prefix in p:
q("UPDATE ip SET last=? WHERE prefix=?", (now, prefix))
if not p[prefix]:
......
......@@ -56,6 +56,11 @@ def getConfig():
help="Exit after configuration parsing. Status code is the"
" result of the given Python expression. For example:\n"
" main_interface != 'eth0'")
_('--console', metavar='SOCK',
help="Socket path to Python console that can be used to inspect or"
" patch this process. Use:\n"
" socat - UNIX:<SOCK>\n"
"to access it.")
_ = parser.add_argument_group('routing').add_argument
_('-B', dest='babel_args', metavar='ARG', action='append', default=[],
......@@ -266,7 +271,8 @@ def main():
remote_gateway, config.disable_proto, config.neighbour)
config.babel_args += tunnel_manager.new_iface_list
else:
tunnel_manager = tunnel.BaseTunnelManager(cache, cert, address)
tunnel_manager = tunnel.BaseTunnelManager(control_socket,
cache, cert, address)
cleanup.append(tunnel_manager.sock.close)
try:
......@@ -274,7 +280,7 @@ def main():
ipv4 = getattr(cache, 'ipv4', None)
if ipv4:
serial = int(cert.cert.get_subject().serialNumber)
serial = cert.subject_serial
if cache.ipv4_sublen <= 16 and serial < 1 << cache.ipv4_sublen:
dot4 = lambda x: socket.inet_ntoa(struct.pack('!I', x))
ip4('route', 'unreachable', ipv4, 'proto', 'static')
......@@ -389,10 +395,23 @@ def main():
tunnel_manager.killAll)
except AttributeError:
pass
if config.console:
from re6st.debug import Console
def console(socket, frame=sys._getframe()):
try:
import pdb; pdb.Pdb(stdin=socket,
stdout=socket).set_trace()
frame.f_locals # main() locals
finally:
socket.close()
console = Console(config.console, console)
cleanup.append(console.close)
# main loop
exit.release()
select_list = [forwarder.select] if forwarder else []
if config.console:
select_list.append(console.select)
select_list += tunnel_manager.select, utils.select
while True:
args = R.copy(), {}, []
......
......@@ -79,15 +79,16 @@ def main():
_('--key', required=True,
help="CA private key in .pem format. For example:\nopenssl"
" genpkey -out ca.key -algorithm rsa -pkeyopt rsa_keygen_bits:2048")
_('--mailhost', required=True,
_('--mailhost', default=None,
help="SMTP host to send confirmation emails. For debugging"
" purpose, it can also be an absolute or existing path to"
" a mailbox file")
" a mailbox file. If unset, registration by mail is disabled.")
_('--prefix-length', default=16, type=int,
help="Default length of allocated prefixes.")
help="Default length of allocated prefixes."
" If 0, registration by email is disabled.")
_('--anonymous-prefix-length', type=int,
help="Length of allocated anonymous prefixes."
" If 0 or unset, registration by email is required")
" If 0 or unset, anonymous registration is disabled.")
_('--ipv4', nargs=2, metavar=("IP/N", "PLEN"),
help="Enable ipv4. Each node is assigned a subnet of length PLEN"
" inside network IP/N.")
......@@ -101,6 +102,8 @@ def main():
" 3=DEBUG, 4=TRACE. Use SIGUSR1 to reopen log.")
_('--min-protocol', default=version.min_protocol, type=int,
help="Reject nodes that are too old. Current is %s." % version.protocol)
_('--authorized-origin', action='append', default=['127.0.0.1', '::1'],
help="Authorized IPs to access origin-restricted RPC.")
_ = parser.add_argument_group('routing').add_argument
_('--hello', type=int, default=15,
......
......@@ -206,7 +206,7 @@ class Babel(object):
try:
s.connect(self.socket_path)
except socket.error, e:
logging.debug("%s", e)
logging.debug("Can't connect to %r (%r)", self.socket_path, e)
return e
s.send("\1")
s.setblocking(0)
......@@ -276,7 +276,20 @@ class Babel(object):
prefix = ip[a:route.plen]
if prefix and not route.refmetric:
neighbours[prefix] = neigh_routes
unidentified.remove(address)
# XXX: Temporary logging to understand when a KeyError
# happens. Then, we'll problably replace 'remove' by
# 'discard'.
try:
unidentified.remove(address)
except KeyError as e:
logging.warning("address: %s; prefix: %s",
address, prefix)
logging.warning("neighbours: %r", neighbours)
logging.warning("routes: %r", routes)
try:
tm.sendto(tm.cache.registry_prefix, '\7%s' % e)
except AttributeError:
pass
else:
prefix = None
neigh_routes[1][prefix] = route
......@@ -297,3 +310,24 @@ class Babel(object):
def handle_set_cost_multiplier(self, flags):
pass
class iterRoutes(object):
_waiting = True
def __new__(cls, control_socket, network):
self = object.__new__(cls)
c = Babel(control_socket, self, network)
c.request_dump()
while self._waiting:
args = {}, {}, ()
c.select(*args)
utils.select(*args)
return (prefix
for neigh_routes in c.neighbours.itervalues()
for prefix in neigh_routes[1]
if prefix)
def babel_dump(self):
self._waiting = False
import errno, os, socket, stat, threading
class Socket(object):
def __init__(self, socket):
# In case that the default timeout is not None.
socket.settimeout(None)
self._socket = socket
self._buf = ''
def close(self):
self._socket.close()
def write(self, data):
self._socket.send(data)
def readline(self):
recv = self._socket.recv
data = self._buf
while True:
i = 1 + data.find('\n')
if i:
self._buf = data[i:]
return data[:i]
d = recv(4096)
data += d
if not d:
self._buf = ''
return data
def flush(self):
pass
def closed(self):
self._socket.setblocking(0)
try:
self._socket.recv(0)
return True
except socket.error, (err, _):
if err != errno.EAGAIN:
raise
self._socket.setblocking(1)
return False
class Console(object):
def __init__(self, path, pdb):
self.path = path
s = socket.socket(socket.AF_UNIX)
try:
self.close()
except OSError, e:
if e.errno != errno.ENOENT:
raise
s.bind(path)
s.listen(5)
def accept():
t = threading.Thread(target=pdb, args=(Socket(s.accept()[0]),))
t.daemon = True
t.start()
def select(r, w, t):
r[s] = accept
self.select = select
def close(self):
if stat.S_ISSOCK(os.lstat(self.path).st_mode):
os.remove(self.path)
......@@ -23,7 +23,7 @@ def openvpn(iface, encrypt, *args, **kw):
logging.debug('%r', args)
return utils.Popen(args, **kw)
ovpn_link_mtu_dict = {'udp': 1434, 'udp6': 1450}
ovpn_link_mtu_dict = {'udp': 1432, 'udp6': 1450}
def server(iface, max_clients, dh_path, fd, port, proto, encrypt, *args, **kw):
client_script = '%s %s' % (ovpn_server, fd)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -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 = 1
protocol = 3
min_protocol = 1
if __name__ == "__main__":
......
# -*- coding: utf-8 -*-
import calendar, hashlib, hmac, logging, os, struct, subprocess, threading, time
from collections import deque
from datetime import datetime
from OpenSSL import crypto
from . import utils
......@@ -106,6 +105,10 @@ class Cert(object):
def network(self):
return networkFromCa(self.ca)
@property
def subject_serial(self):
return int(self.cert.get_subject().serialNumber)
@property
def openvpn_args(self):
return ('--ca', self.ca_path,
......@@ -164,12 +167,12 @@ class Peer(object):
hello0: 0, A
1, fingerprint(B), A
hello: 2, X = E(B)(secret), S(A)(X)
!hello: #, ver, type, value, HMAC(secret)(payload)
└──── payload ────┘
hello: 2, X = encrypt(B, secret), sign(A, X)
!hello: #, type, value, hmac(secret, payload)
└── payload ──┘
new secret > old secret
(concat timestamp with random bits)
(timestamp + random bits)
Reject messages with # smaller or equal than previously processed.
......@@ -198,6 +201,8 @@ class Peer(object):
def connected(self):
return self._last is None or time.time() < self._last + 60
subject_serial = Cert.subject_serial
def __ne__(self, other):
raise AssertionError
__eq__ = __ge__ = __le__ = __ne__
......