User Tools

Site Tools


vpn

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
vpn [2020/08/13 13:23]
robm created
vpn [2022/11/30 12:35] (current)
robm
Line 88: Line 88:
   - **As root** on your client system, generate a new SSH keypair to use for VPN. <code>ssh-keygen -f ~/.ssh/id_rsa_vpn -N ''</code>   - **As root** on your client system, generate a new SSH keypair to use for VPN. <code>ssh-keygen -f ~/.ssh/id_rsa_vpn -N ''</code>
   - Install new public key into remote system, and prefix with a ForeCommand which is run whenever this key is used to authenticate:<code>( \   - Install new public key into remote system, and prefix with a ForeCommand which is run whenever this key is used to authenticate:<code>( \
-  printf 'tunnel="0",command="ifconfig tun0 inet 172.16.0.1 dstaddr 172.16.0.2" ' ; \+  printf 'tunnel="0",command="fuser -k /dev/net/tun; ifconfig tun0 inet 172.16.0.1 dstaddr 172.16.0.2" ' ; \
   cat ~/.ssh/id_rsa_test.pub \   cat ~/.ssh/id_rsa_test.pub \
 ) | ssh root@www.robmeerman.co.uk tee -a .ssh/authorized_keys</code> ) | ssh root@www.robmeerman.co.uk tee -a .ssh/authorized_keys</code>
Line 95: Line 95:
   User root   User root
   # Remote's .ssh/authorised_keys entry for this identity is prefixed with:   # Remote's .ssh/authorised_keys entry for this identity is prefixed with:
-  # tunnel="0",command="ifconfig tun0 inet 172.16.0.1 dstaddr 172.16.0.2" ssh-rsa+  # tunnel="0",command="fuser -k /dev/net/tun; ifconfig tun0 inet 172.16.0.1 dstaddr 172.16.0.2" ssh-rsa
   IdentityFile ~root/.ssh/id_rsa_vpn   IdentityFile ~root/.ssh/id_rsa_vpn
   Tunnel yes   Tunnel yes
Line 157: Line 157:
  
 # ( \ # ( \
-#   printf 'tunnel="0",command="ifconfig tun0 inet 172.16.0.1 dstaddr 172.16.0.2" ' ; \+#   printf 'tunnel="0",command="fuser -k /dev/net/tun; ifconfig tun0 inet 172.16.0.1 dstaddr 172.16.0.2" ' ; \
 #   cat ~/.ssh/id_rsa_test.pub \ #   cat ~/.ssh/id_rsa_test.pub \
 # ) | ssh root@www.robmeerman.co.uk tee -a .ssh/authorized_keys # ) | ssh root@www.robmeerman.co.uk tee -a .ssh/authorized_keys
Line 210: Line 210:
 </code> </code>
  
 +
 +===== KCP Tunnelling via Fast Reverse Proxy (frp) =====
 +
 +[[https://github.com/fatedier/frp|Fast Reverse Proxy (frp)]] is a pair of standalone executables which can be used to expose services behind NAT. I like it because:
 +
 +  * It supports [[https://github.com/skywind3000/kcp/blob/master/README.en.md|KCP protocol]].
 +    * KCP reduces latency on lossy links by implementing error **correction** instead of just the error **detection** of TCP. This is achieved by using more bandwidth to send [[https://en.wikipedia.org/wiki/Erasure_code|erasure codes]] which can be used to recover lost packets (instead of requesting they be retransmitted which add round-trip delays). Similar to how CD-ROMs cope with scratches.
 +    * This is especially useful on cellular / mobile networks (3G, 4G, etc)
 +  * It can NAT-bust, even when **both** parties are behind NAT.
 +    * This does require a public, non-NAT, server both parties can initiate contact with
 +
 +Download and unpack [[https://github.com/fatedier/frp|Fast Reverse Proxy (frp)]] which contains two executables: ''frpc'' and ''frps''.
 +
 +I drive them with this bash script, which I call ''frp'':
 +
 +<code>
 +#!/bin/bash
 +#
 +# FRP: Fast Reverse Proxy (cf. https://github.com/fatedier/frp)
 +#
 +# XTCP: Creates a direct connection between hosts which are behind NAT gateways
 +# by getting both to contact a public server they can both access, and then
 +# (ab)using a UDP connection directly to one another. Because UDP is stateless,
 +# both sides can send a packet to the other and thereby get their NAT gateway
 +# to set up a session (temporary port forward) for any return traffic. Voila,
 +# you now have holes in both NAT gateways and the clients (frpc) can talk to
 +# each other directly.
 +
 +SERVER_PORT=29900
 +SERVER_ADDR=203.0.113.0:${SERVER_PORT}
 +TOKEN=yourtokenhere
 +SECRET_KEY=yoursecrethere
 +
 +case $1 in
 +    public-server)
 +        CMD=(
 +            ./frps
 +            --bind_udp_port=7001
 +            --kcp_bind_port=${SERVER_PORT}
 +            --token=${TOKEN}
 +        );;
 +
 +    ssh-server)
 +        CMD=(
 +            ./frpc xtcp 
 +
 +            # Public server details and auth token
 +            --server_addr=${SERVER_ADDR}
 +            --protocol=kcp
 +            --token=${TOKEN}
 +
 +            # Proxy entry to publish for other hosts (also behind NAT) to
 +            # access, thus making us act as a server.
 +            --role=server 
 +            --proxy_name=ssh_p2p 
 +            --sk=${SECRET_KEY}
 +            #    Service to connect incoming tunnelled connections to
 +            --local_ip=127.0.0.1
 +            --local_port=22
 +        );;
 +
 +    ssh-client)
 +        CMD=(
 +            ./frpc xtcp 
 +
 +            # Public server details and auth token
 +            --server_addr=${SERVER_ADDR}
 +            --protocol=kcp
 +            --token=${TOKEN}
 +
 +            # Proxy entry (published by another client) within the server we want to
 +            # use, and server secret key
 +            --server_name=ssh_p2p 
 +            --sk=${SECRET_KEY}
 +            #   As a visitor, we are trying to access something published by another
 +            #   client (also behind NAT) with --role=server. "bind" parameters dictate
 +            #   where to put the listening end of our P2P tunnel: apps on our network
 +            #   will connect to this to be tunnelled through FRP and it's NAT hole.
 +            #
 +            #   Also note that KCP protocol runs over UDP, but very few applications
 +            #   support that directly, so the both ends of the KCP tunnel convert
 +            #   to/from TCP.
 +            --role=visitor 
 +            --bind_addr=127.0.0.1 
 +            --bind_port=29922
 +        );;
 +
 +    *)
 +        echo "Please provide exactly one argument: public-server, ssh-server, or ssh-client"
 +        exit 1
 +        ;;
 +
 +esac
 +
 +cd $(dirname $0)
 +exec "${CMD[@]}"
 +</code>
 +
 +and if you like, here's a systemd file for it, ''frp.service'':
 +
 +<code>
 +[Unit]
 +Description=Fast Reliable Proxy Server
 +After=network.target
 +
 +[Service]
 +Type=simple
 +User=nobody
 +Restart=on-failure
 +RestartSec=5s
 +ExecStart=/opt/frp/frp public-server
 +
 +[Install]
 +WantedBy=multi-user.target
 +</code>
 +
 +To install it:
 +
 +    sudo ln -s $(readlink -f frp.service) /etc/systemd/system/
 +    sudo systemctl daemon-reload  # To notice the new symbolic link
 +    sudo systemctl enable frp.service  # So it starts automatically on boot
 +    sudo systemctl start frp.service  # .. one off start it now
vpn.txt · Last modified: 2022/11/30 12:35 by robm