Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
R
re6stnet
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Xiaowu Zhang
re6stnet
Commits
7409e32c
Commit
7409e32c
authored
Aug 03, 2012
by
Guillaume Bury
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed minor bug in db. Added a HOW TO section in re6stnet man page
parent
5f163f16
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
167 additions
and
65 deletions
+167
-65
README
README
+0
-21
TODO
TODO
+4
-4
docs/re6st-conf.rst
docs/re6st-conf.rst
+3
-4
docs/re6st-registry.rst
docs/re6st-registry.rst
+2
-2
docs/re6stnet.rst
docs/re6stnet.rst
+113
-3
re6st-conf
re6st-conf
+11
-3
re6st-registry
re6st-registry
+10
-1
re6st/db.py
re6st/db.py
+21
-16
re6st/tunnel.py
re6st/tunnel.py
+1
-1
re6st/utils.py
re6st/utils.py
+2
-10
No files found.
README
View file @
7409e32c
...
...
@@ -78,24 +78,3 @@ Later....
re6st/upnpigd.py Forward ports
re6st-conf.py Get certificates from server
re6st-registry.py Server : deliver certificates and distribute peers
.. XXX: write monkey-patch in __init__.py
Note: On certain version of python (e.g. 2.7.3~rc2-2.1 ) dns lookup is
performed for each request, and cause a delay in response.
To avoid this, one can either upgrade python, fix their resolv.conf or use
the fix at the end of this file.
--------------------------------------------------------------------------------
# Fix for librpcxml to avoid doing reverse dns on each request
# it was causing a 10s delay on each request when no reverse DNS was avalaible
import BaseHTTPServer
def not_insane_address_string(self):
host, port = self.client_address[:2]
return '%s (reverse DNS disabled)' % host # used to call: socket.getfqdn(host)
BaseHTTPServer.BaseHTTPRequestHandler.address_string = not_insane_address_string
--------------------------------------------------------------------------------
TODO
View file @
7409e32c
To be done :
Male sure the re6stnet ip address is added on only one interface
( tweak the ovpn-server script ), else duplicate addresses appears in routing
tables.
Use an algorithm to choose which connections to keep and/or establish
instead of pure randomness
number of routes / tunnel
README : move options doc elsewhere, make it look like a real readme
Use latency in babeld
Warn babeld about the tunnels wich are about to be deleted. Maybe we could just increase the cost.
docs/re6st-conf.rst
View file @
7409e32c
...
...
@@ -12,8 +12,8 @@ Configuration tool for re6stnet
SYNOPSIS
========
``re6st-conf`` ``--server`` `server-url` ``--port`` `server-port`
[`command`]
[`options`...]
``re6st-conf`` ``--server`` `server-url` ``--port`` `server-port`
[`command`]
[`options`...]
DESCRIPTION
===========
...
...
@@ -59,13 +59,12 @@ Options
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 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
-r, ``--req`` `name` `value`
Specify an attribute to add to the certificate request sent to the
server. Can be used multiple times.
...
...
docs/re6st-registry.rst
View file @
7409e32c
...
...
@@ -13,8 +13,8 @@ SYNOPSIS
========
``re6st-registry`` `port` ``--db`` `db-path` ``--ca`` `ca-path`
``--key`` `key-path` ``--mailhost`` `mailhost
`
``--private`` `private-ip`
[`options`...]
``--key`` `key-path` ``--mailhost`` `mailhost` ``--private`` `private-ip
`
[`options`...]
DESCRIPTION
===========
...
...
docs/re6stnet.rst
View file @
7409e32c
...
...
@@ -12,9 +12,9 @@ Resilient, Scalable, IPv6 Network application
SYNOPSIS
========
``re6stnet`` ``--registry`` `registry-url` ``--dh`` `dh-path`
``--ca`` `ca-path` ``--cert`` `cert-path`
``--key`` `key-path` [`options`...]
[``--`` [`openvpn-options`...]]
``re6stnet`` ``--registry`` `registry-url` ``--dh`` `dh-path`
``--ca`` `ca-path`
``--cert`` `cert-path` ``--key`` `key-path` [`options`...]
[``--`` [`openvpn-options`...]]
DESCRIPTION
===========
...
...
@@ -164,6 +164,116 @@ Openvpn-options
be passed down to ALL openvpn processes ( including servers )
exactly as they are given.
HOW TO
======
Here's an example how to deploy your re6st network.
Normal node
-----------
In most cases, you only have to start the re6stnet daemon for you to join
the re6st network. Since the number of options to set is currently quite high,
I advise you to utse a configuration file. Here is an example of such a
configuration file::
# Configuration file for re6stnet
# You have to give the complete url of the re6st-registry.
# If you have the ip address and the port of the registry, enter the url as
# following :
# registry http://ipv4:port
# registry http://[ipv6]:port
registry http://localhost:8000
# Here are information about your certificates.
# These options are mandatory.
dh dh2048.pem
ca ca.pem
cert cert.crt
key cert.key
# You can give the external configuration ( ip, port and protocol )
# advertised to other nodes. These information are used by the openvpn
# daemon to connect to your servers. If no --ip otion is given, re6stnet
# will automatically attempt to forward ports vie UPnP.
# You can give as many --ip options you want.
# ip 192.0.2.130 1194 udp
# ip 192.0.2.130 1194 tcp-client
# You can specify the directory you want the state files ( peer database,
# babel state file ), to be in. The default is :
# state /var/lib/re6stnet
# Verbose level ( default: 0 )
# 1 is a good verbose level if you want to see what's happening in re6st.
# level 2 and 3 display a whole lot of messages, so it should only be used
# as a debug tool
verbose 1
You can then start re6stnet :
``re6stnet @command_file``
First Node
----------
First, generate the ceritifcates for your network with the following command.
For that, you have to give the address for your network, here we took an
address starting with the ipv6 example prefix `2001:db8::`, and adding a random
number to create a /48 network. Once you have decided on your network ip
address, you have to translate it into hexadecimal, and add a **1** as the
most significant digit. So the network ip address 2001:db8:42::/48 translate
into ``0x120010db80042``. Put that number as the serial umber of your
certificate.
``openssl req -nodes -new -x509 -key ca.key -set_serial 0x120010db80042
-days 365 -out ca.crt``
With this, you now have a ca.crt and a ca.key file in your current directory.
Then, you have to start a re6st-registry to acquire an ipv6 address for your
first node. In order to do that, you need to run the following command.
You can give any path you like for the --db option, if the file does not
exists, it will be created. The mailhost will be used to send tokens by mail,
so you should make sure it works.
``re6st-registry port_number --db db_path --ca path_to_ca.crt
--key path_to_ca.key --mailhost yourmailhost``
You are now ready to use the re6st configuration tool to generate the
certificates for the first node of your network, i.e. you. This should do the
trick :
``re6st-conf --server localhost --port 8000``
It will generate in your local directory (you can change it with the -d option)
four files (ca.crt, cert.crt, cert.key, dh2048.pem).
Now here's the tricky part. For your network to work, you need to restart the
registry (maybe it will be fixed one day...), this time with more information
than the last time. You need to get your hands on the individual prefix of your
node, and the re6st ipv6 address associated. These should have been printed
at the end of re6st-conf. If you have missed them, for one reason or another,
you can get them in the python interpreter::
>>> from re6st import utils
>>> network = utils.networkFromCa('ca.pem')
>>> re6st_ip, prefix = utils.ipFromCert(network, 'cert.crt')
>>> print re6st_ip
2001:0db8:0042:0003:0000:0000:0000:0001
>>> print prefix
0000000000000011
Now you can restart your re6st-registry with two more options:
``re6st-registry port_number --db db_path --ca path_to_ca.crt
--key path_to_ca.key --mailhost yourmailhost --private 2001:db8:42:3::1
--bootstrap 0000000000000011``
Finally, you can start your own re6st node following the instrucxtions in the
precedent section.
SEE ALSO
========
...
...
re6st-conf
View file @
7409e32c
...
...
@@ -19,13 +19,16 @@ def main():
_
(
'--email'
,
help
=
'Your email address'
)
_
(
'--token'
,
help
=
'The token you received'
)
config
=
parser
.
parse_args
()
ca_path
=
os
.
path
.
join
(
config
.
dir
,
'ca.pem'
)
cert_path
=
os
.
path
.
join
(
config
.
dir
,
'cert.crt'
)
key_path
=
os
.
path
.
join
(
config
.
dir
,
'cert.key'
)
# Establish connection with server
s
=
xmlrpclib
.
ServerProxy
(
'http://%s:%u'
%
(
config
.
server
,
config
.
port
))
# Get CA
ca
=
s
.
getCa
()
with
open
(
os
.
path
.
join
(
config
.
dir
,
'ca.pem'
)
,
'w'
)
as
f
:
with
open
(
ca_path
,
'w'
)
as
f
:
f
.
write
(
ca
)
if
config
.
ca_only
:
...
...
@@ -56,9 +59,9 @@ def main():
cert
=
s
.
requestCertificate
(
config
.
token
,
req
)
# Store cert and key
with
open
(
os
.
path
.
join
(
config
.
dir
,
'cert.key'
)
,
'w'
)
as
f
:
with
open
(
key_path
,
'w'
)
as
f
:
f
.
write
(
key
)
with
open
(
os
.
path
.
join
(
config
.
dir
,
'cert.crt'
)
,
'w'
)
as
f
:
with
open
(
cert_path
,
'w'
)
as
f
:
f
.
write
(
cert
)
# Generating dh file
...
...
@@ -67,5 +70,10 @@ def main():
print
"Certificate setup complete."
network
=
utils
.
networkFromCa
(
ca_path
)
internal_ip
,
prefix
=
utils
.
ipFromCert
(
network
,
cert_path
)
print
"Your re6st ip : %s"
%
internal_ip
print
"Your prefix : %s"
%
prefix
if
__name__
==
"__main__"
:
main
()
re6st-registry
View file @
7409e32c
...
...
@@ -23,6 +23,10 @@ class SimpleXMLRPCServer4(SimpleXMLRPCServer):
allow_reuse_address
=
True
def
address_string
(
self
):
# Workaround for http://bugs.python.org/issue6085
return
self
.
client_address
[
0
]
class
SimpleXMLRPCServer6
(
SimpleXMLRPCServer4
):
...
...
@@ -59,10 +63,15 @@ class main(object):
_
(
'--bootstrap'
,
action
=
"append"
,
help
=
'''VPN prefix of the peers to send as bootstrap peer,
instead of random ones'''
)
_
(
'--private'
,
required
=
True
,
_
(
'--private'
,
help
=
'VPN IP of the node on which runs the registry'
)
self
.
config
=
parser
.
parse_args
()
if
not
self
.
config
.
private
:
logging
.
warning
(
'You have declared no private address'
', either this is the first start, or you should'
'check you configuration'
)
# Database initializing
self
.
db
=
sqlite3
.
connect
(
self
.
config
.
db
,
isolation_level
=
None
)
self
.
db
.
execute
(
"""CREATE TABLE IF NOT EXISTS peers (
...
...
re6st/db.py
View file @
7409e32c
...
...
@@ -27,17 +27,18 @@ class PeerManager:
used INTEGER NOT NULL DEFAULT 0,
date INTEGER DEFAULT (strftime('%s', 'now')))"""
)
self
.
_db
.
execute
(
"UPDATE peers SET used = 0"
)
self
.
_db
.
execute
(
"CREATE INDEX IF NOT EXISTS _peers_used ON peers(used)"
)
self
.
_db
.
execute
(
"""CREATE TABLE IF NOT EXISTS blacklist (
prefix TEXT PRIMARY KEY,
flag INTEGER NOT NULL)"""
)
self
.
_db
.
execute
(
"""CREATE INDEX IF NOT EXISTS
blacklist_flag ON blacklist(flag)"""
)
self
.
_db
.
execute
(
"INSERT OR REPLACE INTO blacklist VALUES (?,?)"
,
(
prefix
,
1
))
self
.
_db
.
execute
(
"CREATE INDEX IF NOT EXISTS
_peers_used ON peers(used)"
)
self
.
_db
.
execute
(
"""CREATE TABLE IF NOT EXISTS config (
name text primary key,
value text)"""
)
self
.
_db
.
execute
(
'ATTACH DATABASE ":memory:" AS blacklist'
)
self
.
_db
.
execute
(
"""CREATE TABLE blacklist.flag (
prefix TEXT PRIMARY KEY,
flag INTEGER NOT NULL)"""
)
self
.
_db
.
execute
(
"""CREATE INDEX blacklist.blacklist_flag
ON flag(flag)"""
)
self
.
_db
.
execute
(
"INSERT INTO blacklist.flag VALUES (?,?)"
,
(
prefix
,
1
))
try
:
a
,
=
self
.
_db
.
execute
(
"SELECT value FROM config WHERE name='registry'"
).
next
()
except
StopIteration
:
...
...
@@ -51,20 +52,20 @@ class PeerManager:
def
clear_blacklist
(
self
,
flag
):
logging
.
info
(
'Clearing blacklist from flag %u'
%
flag
)
self
.
_db
.
execute
(
"DELETE FROM blacklist WHERE flag = ?"
,
self
.
_db
.
execute
(
"DELETE FROM blacklist
.flag
WHERE flag = ?"
,
(
flag
,))
logging
.
info
(
'Blacklist cleared'
)
def
blacklist
(
self
,
prefix
,
flag
):
logging
.
ninfo
(
'Blacklisting %s'
%
prefix
)
self
.
_db
.
execute
(
"DELETE FROM peers WHERE prefix = ?"
,
(
prefix
,))
self
.
_db
.
execute
(
"INSERT OR REPLACE INTO blacklist VALUES (?,?)"
,
self
.
_db
.
execute
(
"INSERT OR REPLACE INTO blacklist
.flag
VALUES (?,?)"
,
(
prefix
,
flag
))
logging
.
debug
(
'%s blacklisted'
%
prefix
)
def
whitelist
(
self
,
prefix
):
logging
.
info
(
'Unblacklisting %s'
%
prefix
)
self
.
_db
.
execute
(
"DELETE FROM blacklist WHERE prefix = ?"
,
(
prefix
,))
self
.
_db
.
execute
(
"DELETE FROM blacklist
.flag
WHERE prefix = ?"
,
(
prefix
,))
logging
.
debug
(
'%s whitelisted'
%
prefix
)
def
refresh
(
self
):
...
...
@@ -102,7 +103,7 @@ class PeerManager:
self
.
_db
.
executemany
(
"""INSERT OR IGNORE INTO peers (prefix, address)
VALUES (?,?)"""
,
new_peer_list
)
self
.
_db
.
execute
(
"""DELETE FROM peers WHERE prefix IN
(SELECT prefix FROM blacklist)"""
)
(SELECT prefix FROM blacklist
.flag
)"""
)
logging
.
info
(
'DB populated'
)
logging
.
trace
(
'New peers : %s'
%
(
', '
.
join
(
map
(
str
,
new_peer_list
)),))
...
...
@@ -111,8 +112,11 @@ class PeerManager:
peer_list
=
self
.
_db
.
execute
(
"""SELECT prefix, address FROM peers WHERE used
<= 0 ORDER BY used DESC,RANDOM() LIMIT ?"""
,
(
peer_count
,)).
fetchall
()
if
peer_list
or
populate
()
:
if
peer_list
:
return
peer_list
populate
()
logging
.
warning
(
'Cannot find any new peers'
)
return
[]
def
_bootstrap
(
self
):
logging
.
info
(
'Getting Boot peer...'
)
...
...
@@ -123,9 +127,10 @@ class PeerManager:
p
=
subprocess
.
Popen
((
'openssl'
,
'rsautl'
,
'-decrypt'
,
'-inkey'
,
self
.
_key_path
),
stdin
=
subprocess
.
PIPE
,
stdout
=
subprocess
.
PIPE
)
bootpeer
=
p
.
communicate
(
bootpeer
)[
0
].
split
()
self
.
_db
.
execute
(
"INSERT INTO peers (prefix, address) VALUES (?,?)"
,
bootpeer
)
logging
.
debug
(
'Boot peer added'
)
return
True
if
bootpeer
[
0
]
!=
self
.
_prefix
:
self
.
_db
.
execute
(
"INSERT INTO peers (prefix, address) VALUES (?,?)"
,
bootpeer
)
logging
.
debug
(
'Boot peer added'
)
return
True
except
socket
.
error
:
pass
except
sqlite3
.
IntegrityError
,
e
:
...
...
re6st/tunnel.py
View file @
7409e32c
...
...
@@ -88,7 +88,7 @@ class TunnelManager:
self
.
_client_count
=
(
connection_count
+
1
)
//
2
self
.
_refresh_count
=
refresh_count
self
.
free_interface_set
=
set
(
'
clien
t'
+
str
(
i
)
self
.
free_interface_set
=
set
(
'
re6stne
t'
+
str
(
i
)
for
i
in
xrange
(
1
,
self
.
_client_count
+
1
))
def
refresh
(
self
):
...
...
re6st/utils.py
View file @
7409e32c
...
...
@@ -3,7 +3,6 @@ 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'
,
...
...
@@ -11,12 +10,10 @@ 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
=
''
...
...
@@ -24,20 +21,17 @@ def ipFromBin(prefix):
ip
+=
prefix
[
i
:
i
+
4
]
+
':'
return
ip
.
rstrip
(
':'
)
def
ipFromPrefix
(
re6stnet
,
prefix
,
prefix_len
):
prefix
=
bin
(
int
(
prefix
))[
2
:].
rjust
(
prefix_len
,
'0'
)
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
:
...
...
@@ -46,10 +40,8 @@ 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_str
(
address
):
return
';'
.
join
(
map
(
','
.
join
,
address
))
def
address_list
(
address_list
):
return
list
(
tuple
(
address
.
split
(
','
))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment