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
Boris Kocherov
re6stnet
Commits
0ee76b06
Commit
0ee76b06
authored
Jul 26, 2012
by
Guillaume Bury
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Better handling of the connection to registry ( public/private address )
parent
66582a60
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
161 additions
and
146 deletions
+161
-146
README
README
+17
-7
db.py
db.py
+82
-85
registry.py
registry.py
+19
-6
tunnel.py
tunnel.py
+1
-1
vifibnet.py
vifibnet.py
+42
-47
No files found.
README
View file @
0ee76b06
...
...
@@ -25,6 +25,11 @@ OPTIONS : REGISTRY.PY
port
The port on which the server will listen
--private ip
Ipv6 address of the vifibnet client running on the machine. This
address will be advertised only to nodes having a valid
certificate.
--db path
Path to the server Database file. A new DB file will be created
and correctly initialized if the file doesn't exists.
...
...
@@ -42,6 +47,14 @@ OPTIONS : REGISTRY.PY
Path to the server key file. To generate a key file, see the --ca
option
--bootstrap prefix ip port proto
Connection informations of a node given to other as a bootstrap
node to initiate connection with the network.
Prefix should be the prefix number of a node, given in binary and
with correct length. For instance the VPN address
2001:db8:42:1::/64 ( asusming a network prefix 2001:db8:42::/48 )
corresponds to a prefix 1/16 i.e 0000000000000001.
--mailhost mailhost
Mailhost to be used to send email containing token for registration
...
...
@@ -123,13 +136,10 @@ OPTIONS : VIFIBNET.PY
This parameter is also given to openvpn and babel for their log.
Default : 0
--server address
Ip address of the peer discovery server. SHOULD be an ipv6 address
belonging to the VPN network, as the server only allows requests
from inside the VPN (feature not used now for debugging purposes)
--server-port port
Port number on the peer discovery server to which we connect
--registry address
Complete publi ( reachable from the internet ) address of the machine
running a registry. Will be used to get the pirvate address of the
registry and/or bootstrap peers
--hello duration
Set hello interval, in seconds, for both wired and wireless
...
...
db.py
View file @
0ee76b06
...
...
@@ -5,75 +5,91 @@ import utils
class
PeerManager
:
# internal ip = temp arg/attribute
def
__init__
(
self
,
db_dir_path
,
server
,
server_port
,
refresh_time
,
address
,
def
__init__
(
self
,
db_dir_path
,
registry
,
key_path
,
refresh_time
,
address
,
internal_ip
,
prefix
,
manual
,
pp
,
db_size
):
self
.
_refresh_time
=
refresh_time
self
.
_address
=
address
self
.
_internal_ip
=
internal_ip
self
.
_prefix
=
prefix
self
.
_server
=
server
self
.
_server_port
=
server_port
self
.
_db_size
=
db_size
self
.
_registry
=
registry
self
.
_key_path
=
key_path
self
.
_pp
=
pp
self
.
_blacklist
=
[(
prefix
,)]
self
.
_manual
=
manual
self
.
_proxy
=
xmlrpclib
.
ServerProxy
(
'http://%s:%u'
%
(
server
,
server_port
))
utils
.
log
(
'Connectiong to peers database...'
,
4
)
self
.
_db
=
sqlite3
.
connect
(
os
.
path
.
join
(
db_dir_path
,
'peers.db'
),
isolation_level
=
None
)
utils
.
log
(
'Database opened'
,
5
)
utils
.
log
(
'Preparing peers database...'
,
4
)
self
.
_db
.
execute
(
"""CREATE TABLE IF NOT EXISTS peers (
prefix TEXT PRIMARY KEY,
address TEXT NOT NULL,
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 TABLE IF NOT EXISTS config (
name text primary key,
value text)"""
)
try
:
self
.
_db
.
execute
(
"UPDATE peers SET used = 0"
)
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)"""
)
utils
.
log
(
'Database prepared'
,
5
)
except
sqlite3
.
OperationalError
,
e
:
if
e
.
args
[
0
]
==
'no such table: peers'
:
raise
RuntimeError
else
:
utils
.
log
(
e
,
1
)
except
sqlite3
.
Error
,
e
:
utils
.
log
(
e
,
1
)
a
=
self
.
_db
.
execute
(
"SELECT value FROM config WHERE name='registry'"
).
next
()
except
StopIteration
:
proxy
=
xmlrpclib
.
ServerProxy
(
registry
)
a
=
proxy
.
getPrivateAddress
()
self
.
_db
.
execute
(
"INSERT INTO config VALUES ('registry',?)"
,
a
)
self
.
_proxy
=
xmlrpclib
.
ServerProxy
(
a
)
utils
.
log
(
'Database prepared'
,
5
)
self
.
next_refresh
=
time
.
time
()
def
_boot
(
self
):
utils
.
log
(
'Getting Boot peer...'
,
3
)
try
:
utils
.
log
(
"Contacting registry's private address"
,
5
)
bootpeer
=
self
.
_proxy
.
getBootstrapPeer
(
self
.
_prefix
).
data
except
socket
.
error
,
e
:
utils
.
log
(
"""Registry's private address unreachable,
trying public address"""
)
proxy
=
xmlrpclib
.
ServerProxy
(
self
.
_registry
)
bootpeer
=
proxy
.
getBootstrapPeer
(
self
.
_prefix
).
data
utils
.
log
(
'Boot peer received from server'
,
4
)
p
=
subprocess
.
Popen
((
'openssl'
,
'rsautl'
,
'-decrypt'
,
'-inkey'
,
self
.
_key_path
),
stdin
=
subprocess
.
PIPE
,
stdout
=
subprocess
.
PIPE
)
try
:
prefix
,
address
=
p
.
communicate
(
bootpeer
).
split
()
except
ValueError
:
# DO something
pass
self
.
db
.
execute
(
"INSERT INTO peers (prefix, address) VALUES (?,?)"
,
(
prefix
,
address
))
utils
.
log
(
'Boot peer added'
,
4
)
def
clear_blacklist
(
self
,
flag
):
utils
.
log
(
'Clearing blacklist from flag %u'
%
(
flag
,),
3
)
try
:
with
self
.
_db
:
self
.
_db
.
execute
(
"DELETE FROM blacklist WHERE flag = ?"
,
(
flag
,))
utils
.
log
(
'Blacklist cleared'
,
5
)
except
sqlite3
.
Error
,
e
:
utils
.
log
(
e
,
1
)
self
.
_db
.
execute
(
"DELETE FROM blacklist WHERE flag = ?"
,
(
flag
,))
utils
.
log
(
'Blacklist cleared'
,
5
)
def
blacklist
(
self
,
prefix
,
flag
):
utils
.
log
(
'Blacklisting %s'
%
(
prefix
,),
4
)
try
:
with
self
.
_db
:
self
.
_db
.
execute
(
"DELETE FROM peers WHERE prefix = ?"
,
(
prefix
,))
self
.
_db
.
execute
(
"""INSERT OR REPLACE INTO blacklist
VALUES (?,?)"""
,
(
prefix
,
flag
))
utils
.
log
(
'%s blacklisted'
%
(
prefix
,),
5
)
except
sqlite3
.
Error
,
e
:
utils
.
log
(
e
,
1
)
self
.
_db
.
execute
(
"DELETE FROM peers WHERE prefix = ?"
,
(
prefix
,))
self
.
_db
.
execute
(
"INSERT OR REPLACE INTO blacklist VALUES (?,?)"
,
(
prefix
,
flag
))
utils
.
log
(
'%s blacklisted'
%
(
prefix
,),
5
)
def
whitelist
(
self
,
prefix
):
utils
.
log
(
'Unblacklisting %s'
%
(
prefix
,),
4
)
try
:
with
self
.
_db
:
self
.
_db
.
execute
(
"DELETE FROM blacklist WHERE prefix = ?"
,
(
prefix
,))
utils
.
log
(
'%s whitelisted'
%
(
prefix
,),
5
)
except
sqlite3
.
Error
,
e
:
utils
.
log
(
e
,
1
)
self
.
_db
.
execute
(
"DELETE FROM blacklist WHERE prefix = ?"
,
(
prefix
,))
utils
.
log
(
'%s whitelisted'
%
(
prefix
,),
5
)
def
refresh
(
self
):
utils
.
log
(
'Refreshing the peers DB...'
,
2
)
...
...
@@ -100,59 +116,40 @@ class PeerManager:
utils
.
log
(
'Populating the peers DB...'
,
2
)
new_peer_list
=
self
.
_proxy
.
getPeerList
(
self
.
_db_size
,
self
.
_internal_ip
)
try
:
with
self
.
_db
:
self
.
_db
.
execute
(
"""DELETE FROM peers WHERE used <= 0 ORDER BY
used,random() LIMIT MAX(0, ? + (SELECT
COUNT(*) FROM peers WHERE used <= 0))"""
,
(
str
(
len
(
new_peer_list
)
-
self
.
_db_size
),))
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)"""
)
utils
.
log
(
'DB populated'
,
3
)
utils
.
log
(
'New peers : %s'
%
', '
.
join
(
map
(
str
,
new_peer_list
)),
5
)
except
sqlite3
.
Error
,
e
:
utils
.
log
(
e
,
1
)
with
self
.
_db
:
self
.
_db
.
execute
(
"""DELETE FROM peers WHERE used <= 0 ORDER BY used,
RANDOM() LIMIT MAX(0, ? + (SELECT COUNT(*)
FROM peers WHERE used <= 0))"""
,
(
str
(
len
(
new_peer_list
)
-
self
.
_db_size
),))
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)"""
)
utils
.
log
(
'DB populated'
,
3
)
utils
.
log
(
'New peers : %s'
%
', '
.
join
(
map
(
str
,
new_peer_list
)),
5
)
def
getUnusedPeers
(
self
,
peer_count
):
try
:
return
self
.
_db
.
execute
(
"""SELECT prefix, address FROM peers WHERE used
<= 0 ORDER BY used DESC,RANDOM() LIMIT ?"""
,
(
peer_count
,))
except
sqlite3
.
Error
,
e
:
utils
.
log
(
e
,
1
)
return
[(
'0'
,
''
)]
return
self
.
_db
.
execute
(
"""SELECT prefix, address FROM peers WHERE used
<= 0 ORDER BY used DESC,RANDOM() LIMIT ?"""
,
(
peer_count
,))
def
usePeer
(
self
,
prefix
):
utils
.
log
(
'Updating peers database : using peer '
+
str
(
prefix
),
5
)
try
:
with
self
.
_db
:
self
.
_db
.
execute
(
"UPDATE peers SET used = 1 WHERE prefix = ?"
,
(
prefix
,))
utils
.
log
(
'DB updated'
,
5
)
except
sqlite3
.
Error
,
e
:
utils
.
log
(
e
,
1
)
self
.
_db
.
execute
(
"UPDATE peers SET used = 1 WHERE prefix = ?"
,
(
prefix
,))
utils
.
log
(
'DB updated'
,
5
)
def
unusePeer
(
self
,
prefix
):
utils
.
log
(
'Updating peers database : unusing peer '
+
str
(
prefix
),
5
)
try
:
with
self
.
_db
:
self
.
_db
.
execute
(
"UPDATE peers SET used = 0 WHERE prefix = ?"
,
(
prefix
,))
utils
.
log
(
'DB updated'
,
5
)
except
sqlite3
.
Error
,
e
:
utils
.
log
(
e
,
1
)
self
.
_db
.
execute
(
"UPDATE peers SET used = 0 WHERE prefix = ?"
,
(
prefix
,))
utils
.
log
(
'DB updated'
,
5
)
def
flagPeer
(
self
,
prefix
):
utils
.
log
(
'Updating peers database : flagging peer '
+
str
(
prefix
),
5
)
try
:
with
self
.
_db
:
self
.
_db
.
execute
(
"UPDATE peers SET used = -1 WHERE prefix = ?"
,
(
prefix
,))
utils
.
log
(
'DB updated'
,
5
)
except
sqlite3
.
Error
,
e
:
utils
.
log
(
e
,
1
)
self
.
_db
.
execute
(
"UPDATE peers SET used = -1 WHERE prefix = ?"
,
(
prefix
,))
utils
.
log
(
'DB updated'
,
5
)
def
handle_message
(
self
,
msg
):
script_type
,
arg
=
msg
.
split
()
...
...
registry.py
View file @
0ee76b06
#!/usr/bin/env python
import
argparse
,
math
,
random
,
select
,
smtplib
,
sqlite3
,
string
,
socket
,
time
,
traceback
,
errno
import
argparse
,
math
,
random
,
select
,
smtplib
,
sqlite3
,
string
,
socket
,
time
,
import
subprocess
,
threading
,
traceback
,
errno
from
SimpleXMLRPCServer
import
SimpleXMLRPCServer
,
SimpleXMLRPCRequestHandler
from
email.mime.text
import
MIMEText
from
OpenSSL
import
crypto
import
utils
# To generate server ca and key with serial for 2001:db8:42::/48
# openssl req -nodes -new -x509 -key ca.key -set_serial 0x120010db80042 -days 365 -out ca.crt
...
...
@@ -58,6 +57,8 @@ class main(object):
_
(
'--bootstrap'
,
nargs
=
4
,
action
=
"append"
,
help
=
'''VPN prefix, ip address, port and protocol to send as
bootstrap peers, instead of random ones'''
)
_
(
'--private'
,
help
=
'VPN IP of the node on which runs the registry'
)
self
.
config
=
parser
.
parse_args
()
# Database initializing
...
...
@@ -179,10 +180,14 @@ class main(object):
def
getCa
(
self
,
handler
):
return
crypto
.
dump_certificate
(
crypto
.
FILETYPE_PEM
,
self
.
ca
)
def
getBootstrapPeer
(
self
,
handler
):
def
getPrivateAddress
(
self
,
handler
):
return
'http://[%s]:%u'
%
(
self
.
config
.
private
,
self
.
config
.
port
)
def
getBootstrapPeer
(
self
,
handler
,
client_prefix
):
# TODO: Insert a flag column for bootstrap ready servers in peers
# ( servers which shouldn't go down or change ip and port as opposed to servers owned by particulars )
# that way, we also ascertain that the server sent is not the new node....
cert
=
self
.
db
.
execute
(
"SELECT cert FROM vpn WHERE prefix = ?"
,
(
client_prefix
,))
if
self
.
config
.
bootstrap
:
bootpeer
=
random
.
choice
(
self
.
config
.
bootstrap
)
prefix
=
bootpeer
[
0
]
...
...
@@ -190,8 +195,16 @@ class main(object):
else
:
prefix
,
address
=
self
.
db
.
execute
(
"""SELECT prefix, address
FROM peers ORDER BY random() LIMIT 1"""
)
print
"Sending bootstrap peer (%s, %s)"
%
(
prefix
,
address
)
return
prefix
,
address
r
,
w
=
os
.
pipe
()
try
:
threading
.
Thread
(
target
=
os
.
write
,
args
=
(
w
,
cert
)).
start
()
p
=
subprocess
.
Popen
((
'openssl'
,
'rsautl'
,
'-encrypt'
,
'-certin'
,
'-inkey'
,
'/proc/self/fd/%u'
%
r
),
stdin
=
subprocess
.
PIPE
,
stdout
=
subprocess
.
PIPE
)
print
"Sending bootstrap peer (%s, %s)"
%
(
prefix
,
address
)
return
xmlrpclib
.
Binary
(
p
.
communicate
(
'%s %s'
%
(
prefix
,
address
)))
finally
:
os
.
close
(
r
)
os
.
close
(
w
)
def
declare
(
self
,
handler
,
address
):
print
"declaring new node"
...
...
tunnel.py
View file @
0ee76b06
...
...
@@ -185,4 +185,4 @@ class TunnelManager:
def
killAll
(
self
):
for
prefix
in
self
.
_connection_dict
.
keys
():
self
.
_kill
(
prefix
)
vifibnet.py
View file @
0ee76b06
#!/usr/bin/env python
import
argparse
,
errno
,
os
,
select
,
subprocess
,
time
import
argparse
,
errno
,
os
,
select
,
subprocess
,
sqlite3
,
time
from
argparse
import
ArgumentParser
import
db
,
plib
,
upnpigd
,
utils
,
tunnel
...
...
@@ -17,7 +17,7 @@ class ArgParser(ArgumentParser):
yield
arg
def
ovpnArgs
(
optional_args
,
ca_path
,
cert_path
):
def
ovpnArgs
(
optional_args
,
ca_path
,
cert_path
,
key_path
):
# Treat openvpn arguments
if
optional_args
[
0
]
==
"--"
:
del
optional_args
[
0
]
...
...
@@ -25,6 +25,8 @@ def ovpnArgs(optional_args, ca_path, cert_path):
optional_args
.
append
(
ca_path
)
optional_args
.
append
(
'--cert'
)
optional_args
.
append
(
cert_path
)
optional_args
.
append
(
'--key'
)
optional_args
.
append
(
key_path
)
return
optional_args
...
...
@@ -46,10 +48,8 @@ def getConfig():
help
=
'Defines the verbose level'
)
_
(
'-i'
,
'--interface'
,
action
=
'append'
,
dest
=
'iface_list'
,
default
=
[],
help
=
'Extra interface for LAN discovery'
)
_
(
'--server'
,
required
=
True
,
help
=
"VPN address of the discovery peer server"
)
_
(
'--server-port'
,
required
=
True
,
type
=
int
,
help
=
"VPN port of the discovery peer server"
)
_
(
'--registry'
,
required
=
True
,
help
=
"Complete public address of the discovery peer server"
)
# Routing algorithm options
_
(
'--hello'
,
type
=
int
,
default
=
15
,
...
...
@@ -69,6 +69,8 @@ def getConfig():
help
=
'Path to the certificate authority file'
)
_
(
'--cert'
,
required
=
True
,
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'
)
...
...
@@ -89,7 +91,8 @@ def main():
manual
=
bool
(
config
.
address
)
network
=
utils
.
networkFromCa
(
config
.
ca
)
internal_ip
,
prefix
=
utils
.
ipFromCert
(
network
,
config
.
cert
)
openvpn_args
=
ovpnArgs
(
config
.
openvpn_args
,
config
.
ca
,
config
.
cert
)
openvpn_args
=
ovpnArgs
(
config
.
openvpn_args
,
config
.
ca
,
config
.
cert
,
config
.
key
)
# Set global variables
tunnel
.
log
=
config
.
log
...
...
@@ -119,7 +122,7 @@ def main():
except
upnpigd
.
NoUPnPDevice
:
utils
.
log
(
'No upnp device found'
,
4
)
peer_db
=
db
.
PeerManager
(
config
.
state
,
config
.
server
,
config
.
server_port
,
peer_db
=
db
.
PeerManager
(
config
.
state
,
config
.
registry
,
config
.
peers_db_refresh
,
config
.
address
,
internal_ip
,
prefix
,
manual
,
config
.
pp
,
200
)
tunnel_manager
=
tunnel
.
TunnelManager
(
write_pipe
,
peer_db
,
openvpn_args
,
...
...
@@ -147,47 +150,39 @@ def main():
# main loop
try
:
while
True
:
utils
.
log
(
'Sleeping ...'
,
2
)
nextUpdate
=
min
(
tunnel_manager
.
next_refresh
,
peer_db
.
next_refresh
)
if
forwarder
!=
None
:
nextUpdate
=
min
(
nextUpdate
,
forwarder
.
next_refresh
)
nextUpdate
=
max
(
0
,
nextUpdate
-
time
.
time
())
ready
,
tmp1
,
tmp2
=
select
.
select
([
read_pipe
],
[],
[],
nextUpdate
)
if
ready
:
peer_db
.
handle_message
(
read_pipe
.
readline
())
if
time
.
time
()
>=
peer_db
.
next_refresh
:
peer_db
.
refresh
()
if
time
.
time
()
>=
tunnel_manager
.
next_refresh
:
tunnel_manager
.
refresh
()
if
forwarder
!=
None
and
time
.
time
()
>
forwarder
.
next_refresh
:
forwarder
.
refresh
()
except
KeyboardInterrupt
:
try
:
router
.
terminate
()
except
:
pass
try
:
server_process
.
terminate
()
except
:
pass
tunnel_manager
.
killAll
()
while
True
:
utils
.
log
(
'Sleeping ...'
,
2
)
nextUpdate
=
min
(
tunnel_manager
.
next_refresh
,
peer_db
.
next_refresh
)
if
forwarder
!=
None
:
nextUpdate
=
min
(
nextUpdate
,
forwarder
.
next_refresh
)
nextUpdate
=
max
(
0
,
nextUpdate
-
time
.
time
())
ready
,
tmp1
,
tmp2
=
select
.
select
([
read_pipe
],
[],
[],
nextUpdate
)
if
ready
:
peer_db
.
handle_message
(
read_pipe
.
readline
())
if
time
.
time
()
>=
peer_db
.
next_refresh
:
peer_db
.
refresh
()
if
time
.
time
()
>=
tunnel_manager
.
next_refresh
:
tunnel_manager
.
refresh
()
if
forwarder
!=
None
and
time
.
time
()
>
forwarder
.
next_refresh
:
forwarder
.
refresh
()
finally
:
for
p
in
[
router
]
+
server_process
:
try
:
p
.
terminate
()
except
:
pass
try
:
tunnel_manager
.
killAll
()
except
:
pass
except
sqlite3
.
Error
:
traceback
.
print_exc
()
os
.
rename
(
db_path
,
db_path
+
'.bak'
)
os
.
execvp
(
sys
.
executable
,
sys
.
argv
)
except
KeyboardInterrupt
:
return
0
except
:
try
:
router
.
terminate
()
except
:
pass
try
:
server_process
.
terminate
()
except
:
pass
try
:
tunnel_manager
.
killAll
()
except
:
pass
raise
if
__name__
==
"__main__"
:
main
()
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