Setting up VPN tunnel over SSH to your robot
This guide will demonstrate how to setup a VPN tunnel (tun0) over SSH to your robot using Formant's port-forwarding capabilities over our peer-to-peer communication channel. Before starting with this guide, make sure you have setup a device with the agent, and have setup on your client machine fctl and configured ssh. This guide is based on the existing SSH VPN community guide.
Device Configuration
Using any editor, open /etc/ssh/sshd_config
and change the "PermitRootLogin" line and add the "PermitTunnel" line:
PermitRootLogin without-password
PermitTunnel yes
Allow NAT.
These commands will enable Network Address Translation (NAT) without the need to reboot (NAT will be persistent). This may already be enabled on your system.
sudo sysctl -w net.ipv4.ip_forward=1
To set as default, using any editor, open /etc/sysctl.conf
and add:
# Needed to add for forwarding
net.ipv4.ip_forward = 1
Create the tun0
network interface by adding a network interface. Create the file /etc/network/interfaces.d/tun0 and add:
iface tun0 inet static
pre-up sleep 5
address 10.0.0.100
pointopoint 10.0.0.200
netmask 255.255.255.0
up arp -sD 10.0.0.200 eth0 pub
The Formant agent runs with it's own user and group (formant:formant) that, by default, has very limited permissions. To enable the agent to create a tun interface we need to add it to the device's sudoers group:
sudo usermod -aG sudo formant
sudo systemctl restart formant-agent
Note: the formant user has no shell or login by design.
Client Configuration
Generate a ssh key, here we call it formant-vpn:
ssh-keygen -f formant-vpn -b 4096
Put the private key formant-vpn in /root/.ssh and set permissions:
# create this directory if it doesn't exist
sudo mkdir -p /root/.ssh
sudo cp formant-vpn /root/.ssh/formant-vpn
sudo chown root:root /root/.ssh/formant-vpn
sudo chmod 400 /root/.ssh/formant-vpn
Copy the public key formant-vpn.pub onto the device. Once there add it to the authorized keys (Run this ON the device):
# if the root ssh folder doesn't exist, create it
sudo mkdir -p /root/.ssh
sudo bash -c "cat formant-vpn.pub >> /root/.ssh/authorized_keys"
Setup the root user ssh_config by adding this snippet to /root/.ssh/config:
Host *.formant
ProxyCommand fctl port-forward $(echo %h | sed "s/\.formant$//") -r 127.0.0.1 -p %p
SSH Commands on client
Open a new terminal and run this command to stand up the tunnel
sudo ssh -i /root/.ssh/formant-vpn -Cf -w 0:0 nano.001.formant 'ifdown tun0; ifup tun0'
This is running ssh with tunneling (-w) as well as using compression on the channel (-C) and forking it to the background (-f). Additionally, it tells our device to run ifdown tun0; ifup tun0
Note: You may see RTNETLINK answers: Cannot assign requested address which can happen if you rerun this command (the device may already have it's addresses setup.)
Next we need to setup tun0 on our client machine:
sudo ip link set tun0 up
sudo ip addr add 10.0.0.200/32 peer 10.0.0.100 dev tun0
sudo ip route add 10.0.0.0/24 via 10.0.0.200
Which configures tun0 on the client machine and routes traffic on 10.0.0.0/24 back to our device.
You can check the tunnel is established with:
ifconfig
and you should see something like the following on the client machine:
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet 10.0.0.200 netmask 255.255.255.255 destination 10.0.0.100
inet6 fe80::45f3:9856:2ef0:9b50 prefixlen 64 scopeid 0x20<link>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC)
RX packets 4 bytes 192 (192.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1 bytes 48 (48.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
and on the device:
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet 10.0.0.100 netmask 255.255.255.255 destination 10.0.0.200
inet6 fe80::1fc:7f5f:6948:9e8d prefixlen 64 scopeid 0x20<link>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC)
RX packets 80 bytes 12604 (12.6 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 90 bytes 13785 (13.7 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Try pinging the device from your client machine:
ping 10.0.0.100
To tear down the connection get the pid of the ssh command:
ps aux | grep ssh
Once you have the pid you can kill it:
sudo kill -9 $pid
The following is a short script to automate the client process. It accepts one input parameter which is the name of the device you are connecting to:
#! /bin/bash -e
device=$1
echo "setting up ssh tunnel..."
sudo ssh -i /root/.ssh/formant-vpn -Cf -w 0:0 $device.formant 'ifdown tun0; ifup tun0'
echo "ssh tunnel setup."
sudo ip link set tun0 up
sudo ip addr add 10.0.0.200/32 peer 10.0.0.100 dev tun0
sudo ip route add 10.0.0.0/24 via 10.0.0.200
echo "tun0 configured"
sleep infinity
Exiting the script will also tear down the ssh tunnel.
If you plan on keeping long-running ssh tunnels to your devices you may want to also set the following in your ssh config:
Host *
ServerAliveInterval 120
ServerAliveCountMax 10
The ServerAliveInterval will send a ping every 120 seconds if there is no activity on the tunnel. The ServerAliveCountMax defines how many consecutive pings are sent before disconnecting.
Updated over 1 year ago