Skip to content

Instantly share code, notes, and snippets.

@prauscher
Last active December 31, 2020 05:40
Show Gist options
  • Save prauscher/b350edeb588b1e0ad5d9 to your computer and use it in GitHub Desktop.
Save prauscher/b350edeb588b1e0ad5d9 to your computer and use it in GitHub Desktop.
Script to generate peerings in dn42
#!/bin/bash
[ $# -ge 6 ] || {
echo "Usage: $0 <NICK> <MAIL> <GPG> <AS> <ENDPOINT> <IPV4> [PORT] [FASTD-PUBKEY]" >&2
exit 1
}
# You may want to change variables below and check if "/etc/bird/bird-dn42.conf"
# is included in your bird-config (same for bird6 with bird6-dn42.conf)
# NO WARRANTY, REALLY READ THIS FILE BEFORE EXECUTING IT!
GPG="gpg"
IPV6_TRANSFER="fe80"
LOCAL_ROUTER='bird' # or 'quagga'
LOCAL_NICK="prauscher"
LOCAL_AS="64720"
LOCAL_TUNNEL="rajesh.prauscher.de"
LOCAL_IPV4="172.22.120.2"
LOCAL_IPV6="${IPV6_TRANSFER}::$(printf "%x" $(( $LOCAL_AS / 65536 )) ):$(printf "%x" $(( $LOCAL_AS % 65536 )) ):$(printf "%x" $(( $RANDOM + 1 )) )"
LOCAL_PORT=52401
while grep -h -R "^bind .*:$LOCAL_PORT" $(dirname "$0") > /dev/null; do
LOCAL_PORT=$(( $LOCAL_PORT + 1 ))
done
LOCAL_MAIL="prauscher@prauscher.de"
LOCAL_KEYID="0x2794c9ad"
LOCAL_SECKEY=$(fastd --generate-key --machine-readable)
LOCAL_PUBKEY=$(echo "secret \"$LOCAL_SECKEY\";" | fastd -c - --machine-readable --show-key)
REMOTE_NICK="$1"
REMOTE_AS="$4"
REMOTE_TUNNEL="$5"
REMOTE_IPV4="$6"
REMOTE_IPV6="${IPV6_TRANSFER}::$(printf "%x" $(( $REMOTE_AS / 65536 )) ):$(printf "%x" $(( $REMOTE_AS % 65536 )) ):$(printf "%x" $(( $RANDOM + 32768 )) )"
REMOTE_PORT="$LOCAL_PORT"
[ "$7" != "" -a "$7" != "-" ] && REMOTE_PORT="$7"
REMOTE_MAIL="$2"
REMOTE_KEYID="$3"
REMOTE_SECKEY="....."
REMOTE_PUBKEY="$8"
[ "$REMOTE_PUBKEY" == "" ] && {
REMOTE_SECKEY=$(fastd --generate-key --machine-readable)
REMOTE_PUBKEY=$(echo "secret \"$REMOTE_SECKEY\";" | fastd -c - --machine-readable --show-key)
}
# sanity checks
echo "$REMOTE_NICK" | grep -E "^[a-zA-Z0-9]{3,8}$" > /dev/null || {
echo "REMOTE_NICK $REMOTE_NICK does not match ^[a-zA-Z0-9]{3,8}$"
exit 101
}
echo "$REMOTE_AS" | grep -E "^[0-9]{1,10}$" > /dev/null || {
echo "REMOTE_AS $REMOTE_AS does not match ^[0-9]{1,10}$"
exit 102
}
[ $UID -eq 0 ] || {
echo "need to run as root"
exit 103
}
# write our config
CONFIG="$(dirname $0)/${LOCAL_PORT:${#LOCAL_PORT}-2}-as$REMOTE_AS-$REMOTE_NICK.fastd"
cat > "$CONFIG" <<EOT
log level info;
interface "dn42$REMOTE_NICK";
mode tun;
mtu 1448;
bind any:$LOCAL_PORT;
method "salsa2012+umac";
secret "$LOCAL_SECKEY";
peer "dn42_${REMOTE_NICK}" {
key "$REMOTE_PUBKEY";
remote "$REMOTE_TUNNEL" port $REMOTE_PORT;
}
on establish "
ip link set up dev \$INTERFACE
ip addr add $LOCAL_IPV4 peer $REMOTE_IPV4/32 dev \$INTERFACE
ip -6 addr add $LOCAL_IPV6/64 dev \$INTERFACE
";
on disestablish "
ip addr flush dev \$INTERFACE
ip link set down dev \$INTERFACE
";
EOT
fastd -d -c "$CONFIG"
if [ "$LOCAL_ROUTER" == "bird" ]; then
cat >> /etc/bird/bird-dn42.conf <<EOT
protocol bgp dn42_$REMOTE_NICK from dn42_peer {
neighbor $REMOTE_IPV4 as $REMOTE_AS;
import where is_valid_as($REMOTE_AS) && is_dn42();
}
EOT
birdc configure
cat >> /etc/bird/bird6-dn42.conf <<EOT
protocol bgp dn42_$REMOTE_NICK from dn42_peer {
neighbor $REMOTE_IPV6 % 'dn42$REMOTE_NICK' as $REMOTE_AS;
import where is_valid_as($REMOTE_AS) && is_ula();
}
EOT
birdc6 configure
elif [ "$LOCAL_ROUTER" == "quagga" ]; then
cat >> /usr/bin/vtysh <<EOT
conf t
router bgp $LOCAL_AS
neighbor $REMOTE_IPV4 remote-as $REMOTE_AS
neighbor $REMOTE_IPV6 remote-as $REMOTE_AS
no neighbor $REMOTE_IPV6 activate
address-family ipv6
neighbor $REMOTE_IPV6 activate
end
wr
EOT
fi
# write peer config
$GPG --keyserver pgp.mit.edu --recv-keys "$REMOTE_KEYID"
sendmail "$REMOTE_MAIL" <<EOT
From: $LOCAL_MAIL
To: $REMOTE_MAIL
Subject: DN42 peering with $LOCAL_NICK
Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="BOUNDARY"
Mime-Version: 1.0
multipart mail
--BOUNDARY
Content-Type: application/pgp-encrypted
Content-Transfer-Encoding: 7bit
Version: 1
--BOUNDARY
Content-Type: application/octet-stream; name="encrypted.asc"
Content-Description: This is a digitally encrypted message part
Content-Transfer-Encoding: 7bit
$($GPG --batch --armor --trust-model always --recipient "$REMOTE_KEYID" --encrypt <<EOC
Content-Type: multipart/mixed; boundary="INNERBOUNDARY"
multipart mail
--INNERBOUNDARY
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Hello,
your configuration file is ready now. Please use the attached file to
establish the tunnel and then configure your router for BGP with the endpoints:
* $LOCAL_IPV4 for IPv4
* $LOCAL_IPV6 % 'dn42$LOCAL_NICK' for IPv6
and AS $LOCAL_AS. If you got any questions regarding deployment, just reply to
this mail to clear everything up :)
Note: Maybe you have to add your secret key to the fastd-configuration. Please
look if the configuration contains ".....".
Greetings,
$LOCAL_NICK (via a robot)
--INNERBOUNDARY
Content-Disposition: attachment; filename="dn42-$LOCAL_NICK.fastd"
Content-Transfer-Encoding: 7bit
Content-Type: application/octet-stream; name="dn42-$LOCAL_NICK.fastd"; charset="UTF-8"
log level info;
interface "dn42$LOCAL_NICK";
mode tun;
mtu 1448;
bind any:$REMOTE_PORT;
method "salsa2012+umac";
secret "$REMOTE_SECKEY";
peer "dn42_${LOCAL_NICK}" {
key "$LOCAL_PUBKEY";
remote "$LOCAL_TUNNEL" port $LOCAL_PORT;
}
on establish "
ip link set up dev \$INTERFACE
ip addr add $REMOTE_IPV4 peer $LOCAL_IPV4/32 dev \$INTERFACE
ip -6 addr add $REMOTE_IPV6/64 dev \$INTERFACE
";
on disestablish "
ip addr flush dev \$INTERFACE
ip link set down dev \$INTERFACE
";
--INNERBOUNDARY--
EOC
)
--BOUNDARY--
EOT
#!/bin/bash
[ $# -ge 6 ] || {
echo "Usage: $0 <NICK> <MAIL> <GPG> <AS> <ENDPOINT> <IPV4> [PORT]" >&2
exit 1
}
# You may want to change variables below and check if "/etc/bird/bird-dn42.conf"
# is included in your bird-config (same for bird6 with bird6-dn42.conf)
# NO WARRANTY, REALLY READ THIS FILE BEFORE EXECUTING IT!
GPG="gpg"
# specify network to use (HOSTNO = first ip, END = last ip)
IPV4_PREFIX="172.20.149"
IPV4_HOSTNO=32
IPV4_END=63
while grep -E -R "^ifconfig ${IPV4_PREFIX}.($(( $IPV4_HOSTNO + 1 ))|$(( $IPV4_HOSTNO + 2 )))" /etc/openvpn > /dev/null; do
IPV4_HOSTNO=$(( $IPV4_HOSTNO + 4 ))
done
# check if network is out of range
if [ $(( $IPV4_HOSTNO + 3 )) -gt $IPV4_END ]; then
echo "IPv4: No free transfer networks found"
exit 201
fi
LOCAL_IPV4="${IPV4_PREFIX}.$(( $IPV4_HOSTNO + 1 ))"
REMOTE_IPV4="${IPV4_PREFIX}.$(( $IPV4_HOSTNO + 2 ))"
LOCAL_ROUTER='bird' # or 'quagga'
LOCAL_NICK="prauscher"
LOCAL_AS="64720"
IPV6_TRANSFER="fdff:$(printf "%x:%x:%x" $(( $LOCAL_AS / 65535 )) $(( $LOCAL_AS % 65535 )) $RANDOM )"
LOCAL_TUNNEL="rajesh.prauscher.de"
LOCAL_IPV4="172.22.120.2"
LOCAL_IPV6="${IPV6_TRANSFER}::$(printf "%x:%x" $(( $LOCAL_AS / 65536 )) $(( $LOCAL_AS % 65536 )) )"
LOCAL_PORT=52301
while grep -R "^lport $LOCAL_PORT" /etc/openvpn > /dev/null; do
LOCAL_PORT=$(( $LOCAL_PORT + 1 ))
done
LOCAL_MAIL="prauscher@prauscher.de"
LOCAL_KEYID="0x966642860aecfc71"
REMOTE_NICK="$1"
REMOTE_AS="$4"
REMOTE_TUNNEL="$5"
REMOTE_IPV4="$6"
REMOTE_IPV6="${IPV6_TRANSFER}::$(printf "%x:%x" $(( $REMOTE_AS / 65536 )) $(( $REMOTE_AS % 65536 )) )"
REMOTE_PORT="${7:-$LOCAL_PORT}"
REMOTE_MAIL="$2"
REMOTE_KEYID="$3"
# sanity checks
echo "$REMOTE_NICK" | grep -E "^[a-zA-Z0-9]{3,8}$" > /dev/null || {
echo "REMOTE_NICK $REMOTE_NICK does not match ^[a-zA-Z0-9]{3,8}$"
exit 101
}
echo "$REMOTE_AS" | grep -E "^[0-9]{1,10}$" > /dev/null || {
echo "REMOTE_AS $REMOTE_AS does not match ^[0-9]{1,10}$"
exit 102
}
[ $UID -eq 0 ] || {
echo "need to run as root"
exit 103
}
# generate openvpn-key
openvpn --genkey --secret /tmp/$$.key
# write our config
CONFIG="/etc/openvpn/dn42_${REMOTE_NICK}.conf"
cat > "$CONFIG" <<EOT
# Peer: $REMOTE_NICK <$REMOTE_MAIL> $REMOTE_KEYID
mode p2p
remote $REMOTE_TUNNEL
lport $LOCAL_PORT
rport $REMOTE_PORT
proto udp
dev-type tun
dev dn42$REMOTE_NICK
tun-ipv6
comp-lzo
<secret>
$(cat /tmp/$$.key)
</secret>
user nobody
group nogroup
persist-key
persist-tun
ifconfig $LOCAL_IPV4 $REMOTE_IPV4
ifconfig-ipv6 $LOCAL_IPV6/64 $REMOTE_IPV6
EOT
systemctl start openvpn@dn42_${REMOTE_NICK}
systemctl enable openvpn@dn42_${REMOTE_NICK}
if [ "$LOCAL_ROUTER" == "bird" ]; then
cat > /etc/bird/bird-dn42.d/$REMOTE_NICK-as$REMOTE_AS.conf <<EOT
# Peer: $REMOTE_NICK <$REMOTE_MAIL> $REMOTE_KEYID (AS: $REMOTE_AS)
protocol bgp dn42_$REMOTE_NICK from dn42_peer {
neighbor $REMOTE_IPV4 as $REMOTE_AS;
import where is_valid_as($REMOTE_AS) && is_dn42();
}
EOT
birdc configure
cat > /etc/bird/bird6-dn42.d/$REMOTE_NICK-as$REMOTE_AS.conf <<EOT
# Peer: $REMOTE_NICK <$REMOTE_MAIL> $REMOTE_KEYID (AS: $REMOTE_AS)
protocol bgp dn42_$REMOTE_NICK from dn42_peer {
# neighbor $REMOTE_IPV6 % 'dn42$REMOTE_NICK' as $REMOTE_AS;
neighbor $REMOTE_IPV6 as $REMOTE_AS;
import where is_valid_as($REMOTE_AS) && is_ula();
}
EOT
birdc6 configure
elif [ "$LOCAL_ROUTER" == "quagga" ]; then
cat >> /usr/bin/vtysh <<EOT
conf t
router bgp $LOCAL_AS
neighbor $REMOTE_IPV4 remote-as $REMOTE_AS
neighbor $REMOTE_IPV6 remote-as $REMOTE_AS
no neighbor $REMOTE_IPV6 activate
address-family ipv6
neighbor $REMOTE_IPV6 activate
end
wr
EOT
fi
# write peer config
$GPG --keyserver pool.sks-keyservers.net --recv-keys "$REMOTE_KEYID"
sendmail -f "$LOCAL_MAIL" "$REMOTE_MAIL" <<EOT
From: $LOCAL_MAIL
To: $REMOTE_MAIL
Subject: DN42 peering with $LOCAL_NICK
Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="BOUNDARY"
Mime-Version: 1.0
multipart mail
--BOUNDARY
Content-Type: application/pgp-encrypted
Content-Transfer-Encoding: 7bit
Version: 1
--BOUNDARY
Content-Type: application/octet-stream; name="encrypted.asc"
Content-Description: This is a digitally encrypted message part
Content-Transfer-Encoding: 7bit
$($GPG --batch --armor --trust-model always --recipient "$REMOTE_KEYID" --encrypt <<EOC
Content-Type: multipart/mixed; boundary="INNERBOUNDARY"
multipart mail
--INNERBOUNDARY
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Hello,
your configuration file is ready now. Please use the attached file to
establish the tunnel and then configure your router for BGP with the endpoints:
* $LOCAL_IPV4 for IPv4
* $LOCAL_IPV6 % 'dn42$LOCAL_NICK' for IPv6
and AS $LOCAL_AS. If you got any questions regarding deployment, just reply to
this mail to clear everything up :)
Greetings,
$LOCAL_NICK (via a robot)
--INNERBOUNDARY
Content-Disposition: attachment; filename="dn42-$LOCAL_NICK.ovpn"
Content-Transfer-Encoding: 7bit
Content-Type: application/x-openvpn-profile; name="dn42-$LOCAL_NICK.ovpn"; charset="UTF-8"
mode p2p
remote $LOCAL_TUNNEL
lport $REMOTE_PORT
rport $LOCAL_PORT
proto udp
dev-type tun
dev dn42$LOCAL_NICK
tun-ipv6
comp-lzo
<secret>
$(cat /tmp/$$.key)
</secret>
user nobody
group nogroup
persist-key
persist-tun
ifconfig $REMOTE_IPV4 $LOCAL_IPV4
ifconfig-ipv6 $REMOTE_IPV6/64 $LOCAL_IPV6
--INNERBOUNDARY--
EOC
)
--BOUNDARY--
EOT
rm /tmp/$$.key
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment