The GNUnet VPN plugin and direct IP routing like this are intended to be complementary to each other… Note that Quagga most probably will propagate GNUnet routes without issue, though the reverse would need some code updates…
Recent developments hastened the need for things like this… and caught the attention of our ISP
I want to create a completely distributed Internet experience, and try to avoid hijacking numbering space wherever possible to do this. This means that we want to avoid registries where you lease naming or numbering resources, and have to return them when you cannot pay any more.
This does include Regional Internet Registries, who lease address space, and most regular domain registries, who may lease names. Also, if something wrong happens, the name or numbers can be recalled.
Other name and numberspaces are typically persistently allocated. These are much more acceptable. This would include IEEE802 MAC addresses, and numbers such as OIDS used in LDAP, X509/SSL and SNMP tend to be permanently assigned to a given purpose.
For IP addresses, I choose the RFC 4193 random self-allocation numberspace of fd00::/8. We are going to use a source of random material for the addresses, so this is fine. There is a list of some of the other prefixes in use.
For resource naming, we can use Multicast DNS, allowing decentralised naming, such as through the [ff0e::fb]:5353 address.
There isn’t a formally allocated top level domain for MDNS, but port 5353 and the multicast addresses have been allocated to a specification that references .local, so we may be able to use that. There are also reserved names such as .test, as this is an experiment.
Further, rather than be a single alternate root as it will be possible, and even desirable, for several services to be able to claim the same name, and users will choose which to resolve by digital signature.
You can create your own VPN using this guide, and experiment with it to become more familiar with it, before deciding to connect with other VPNs, to form part of the collective global vpn, which we can call the GNUbone as a parody on 6bone, or the InterGNU.
Interconnection may be discussed in Main Chat
Firstly, get yourself public IPv6 addresses for your computers. Ensure that packets to fd00::/8 addresses do not escape where they should not, such as by only routing allocated numberspace to the Internet, rather than as a default route.
On Debian GNU/Linux, modprobe ip6_tunnel and add ip6_tunnel to /etc/modules to make it permanent.
Now you can pick some of your computers as VPN nodes. They will be set up essentially the same, as this is a F2F network.
We can use Quagga to do some routing between VPN nodes.
cp /usr/share/doc/quagga/examples/vtysh.conf.sample /etc/vtysh/vtysh.conf
service integrated-vtysh-config username root nopassword
For /etc/quagga/Quagga.conf, in principle it is this, replacing router-id 0.0.0.0 with some 4-octet number unique amongst your VPN nodes.
Choosing a unique number from only 32 bits might seem much more of a problem than the 40-bits of RFC4193, if we use OSPF across the VPN, but it is possible to separate into OSPF islands with BGP links, and redistribute routes between them. So if you use OSPF, you can peer with BGP, and not need to co-ordinate router-id numbers.
router ospf6 router-id 0.0.0.0 area 0.0.0.0 range fd00::/8 interface free0 area 0.0.0.0 interface free1 area 0.0.0.0 !
We do not need the ospf6d.conf or zebra.conf files to contain any settings, as that will just be confusing, though they do need to exist. We will symlink them to /dev/null
ln --symbolic /dev/null /etc/quagga/ospf6d.conf ln --symbolic /dev/null /etc/quagga/zebra.conf
You can then adminsister quagga by running vtysh
I have set up racoon and setkey to handle IPsec between VPN nodes. The certificate files do not exist yet, racoon would read them when the connection is used.
In /etc/ipsec-tools.conf
flush; spdflush;
/etc/racoon/racoon.conf
path pre_shared_key "/etc/racoon/psk.txt";
path certificate "/usr/local/lib/ssl";
remote anonymous {
exchange_mode main;
certificate_type x509 "../../../../var/local/lib/vpn/vpn.crt" "../../../../var/local/lib/vpn/vpn.key";
verify_cert off;
my_identifier asn1dn;
lifetime time 10 second;
peers_identifier asn1dn;
proposal {
encryption_algorithm 3des;
hash_algorithm md5;
authentication_method rsasig;
dh_group modp1024;
}
}
sainfo anonymous {
pfs_group modp768;
encryption_algorithm 3des;
authentication_algorithm hmac_md5;
compression_algorithm deflate;
}
Now you have racoon and quagga running in the background, you can peer your nodes.
First, a sample OpenSSL configuration file, saved to /usr/local/etc/vpnssl.cnf
Other object identifiers may be added as well.
#
# OpenSSL example configuration file.
# This is mostly being used for generation of certificate requests.
#
# This definition stops the following lines choking if HOME isn't
# defined.
HOME = .
RANDFILE = $ENV::HOME/.rnd
# Extra OBJECT IDENTIFIER info:
oid_file = $ENV::HOME/.oid
oid_section = new_oids
# To use this configuration file with the "-extfile" option of the
# "openssl x509" utility, name here the section containing the
# X.509v3 extensions to use:
# extensions =
# (Alternatively, use a configuration file that has only
# X.509v3 extensions in its main [= default] section.)
[ new_oids ]
# We can add new OIDs in here for use by 'ca' and 'req'.
# Add a simple OID like this:
# testoid1=1.2.3.4
# Or use config file substitution like this:
# testoid2=${testoid1}.5.6
streetAddress=2.5.4.9
postalCode=2.5.4.17
favouriteDrink=0.9.2342.19200300.100.1.5
[ policy_match ]
#countryName = match
#stateOrProvinceName = match
#streetAddress = optional
#postalCode = optional
#organizationName = optional
#organizationalUnitName = optional
commonName = supplied
#emailAddress = optional
# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
streetAddress = optional
postalCode = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 1024
default_keyfile = vpn.key
distinguished_name = req_distinguished_name
attributes = req_attributes
# Use extensions on requests and certificates
utf8 = yes
x509_extensions = v3_crt
req_extensions = v3_req
# only want UTF-8 strings
string_mask = utf8only
# we can have many LDAP style attributes
# http://www.alvestrand.no/objectid/2.5.4.html
[ req_distinguished_name ]
commonName = Common Name (eg, YOUR name)
commonName_max = 64
commonName_default = …
[ req_attributes ]
[ v3_req ]
# Extensions to add to a certificate requests
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[ v3_crt ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = CA:true
Now, the main event, /usr/local/sbin/vpn
Adjust by identifying the interface with your public IPv6 address on it, so the number is copied to MYPUB.
The addresses of your peers go replace the example 2001:db8:d0be:f00d::1 2001:db8:d0be:f00d::2 2001:db8:d0be:f00d::3 addresses.
#!/bin/bash
MYPUB=$(ifconfig eth0 | grep Scope:Global | cut -f2- -d":"|cut -f1 -d"/")
MYADDR=2001:db8:d0be:f00d::1 2001:db8:d0be:f00d::2 2001:db8:d0be:f00d::3
if test "$1" == "init"
then
CRT=/var/local/lib/vpn/vpn.crt
KEY=/var/local/lib/vpn/vpn.key
openssl req -config /usr/local/etc/vpnssl.cnf -new -utf8 -x509 -newkey rsa:1024 -out $CRT -keyout $KEY -nodes -days 10203 -set_serial 0 -batch
#openssl x509 -text -noout -nameopt utf8,sep_multiline,oid -in $CRT
function c() { echo fd${1:62:3}${1:65:2}${1:68:3}${1:71:2}${1:74:2}::/128; };
MYPREFIX=$(c "$(openssl x509 -in $CRT -noout -sha1 -fingerprint)")
I=0
for N in $MYADDR
do
if test $N != $MYPUB
then
ip -6 tunnel add free$I mode ip6ip6 remote $N local $MYPUB
ip -6 addr add $MYPREFIX dev free$I
ip link set dev free$I up
# want mDNS to work here as well…
ifconfig free$I multicast
I=$((0${I} + 1))
fi
done
# Use IPsec to cipher all incoming and outgoing data…
setkey -c <<<"
spdadd $MYPREFIX fd00::/8 any -P out ipsec esp/transport//require ah/transport//require;
spdadd fd00::/8 $MYPREFIX any -P in ipsec esp/transport//require ah/transport//require;
"
fi
if test "$1" == "away"
then
I=0
for N in $MYADDR
do
if test $N != $MYPUB
then
ip -6 tunnel del free${I}
I=$((0${I} + 1))
fi
done
fi
Run as vpn init to connect, and vpn away to drop connection. Quagga should detect that links have gone up and add routes as needed. When ping6ing across the VPN, racoon should detect it, and they will then have some protection with IPSec.
As SSL files are generated randomly, deriving the IP address from the key fingerprint, which is hash of the public key, gives some degree of authority over the address selected.
It is possible to persuade Avahi to serve names over the VPN connections, with allow-point-to-point, and may consider using the dns reflector utilities in there as well.
On nodes facing peers, you will want to firewall, so that only packets from and to fd00::/8 will be routed, with possibly some of ff00::/8 as needed.
This should prevent your node being used as an exit node by surprise.
If your default target is DROP, and may want to further adjust the rules such as to require IPsec where you act as a bearer between other parties.
LL=$'fe80::/64'
MC=$'ff00::/8'
FC=$'fd00::/8'
for N in free0 free1 free2
do
ip6tables -A INPUT -i $N -s ${FC} -d ${FC} -j ACCEPT
ip6tables -A OUTPUT -o $N -s ${FC} -d ${FC} -j ACCEPT
ip6tables -A INPUT -i $N -s ${LL} -d ${MC} -j ACCEPT
ip6tables -A OUTPUT -o $N -s ${LL} -d ${MC} -j ACCEPT
ip6tables -A INPUT -i $N -s ${LL} -d ${LL} -j ACCEPT
ip6tables -A OUTPUT -o $N -s ${LL} -d ${LL} -j ACCEPT
for J in free0 free1 free2
do
if test $N != $J
then
ip6tables -A FORWARD -i $N -o $J -s ${FC} -d ${FC} --protocol esp -m ipv6header --header ah,esp -j ACCEPT
fi
done
done
Add connection to wlan mesh 802.11s
This connection I use for the Engenius EPI-3601S card (Atheros PCI). You need a mac address for each virtual device, so can use the mac address from your local ethernet adaptor or bluetooth device to guarantee uniqueness. Otherwise can pick an address from a virtualisation range such as VirtualBox: 08:00:27:??:??:??, it may not be unique but gives better mesh anonymity if that is desired.
iface mesh inet6 manual
pre-up iw phy phy0 interface add $IFACE type mp
#pre-up ifconfig $IFACE hw ether $(ifconfig eth0|grep HWaddr|cut -f3 -d"r")
up ip -6 addr add \
$( c() { echo fd${1:62:3}${1:65:2}${1:68:3}${1:71:2}${1:74:2}:1:${6:0:1}$(printf %x $((${6:1:1}^2)))${6:3:2}:${6:6:2}ff:fe${6:9:2}:${6:12:2}${6:15:2}/64; }; \
c "$(openssl x509 -in /var/local/lib/vpn/vpn.crt -noout -fingerprint)" $(ifconfig $IFACE)) dev $IFACE
post-down iw dev $IFACE del