This is an old revision of the document!
WireGuard
WireGuard is a modern VPN tunnel solution…
Concepts
network
tunnel
keys
Installation
You will also need nftables if you plan to do port-forwarding
emerge -v net-vpn/wireguard-tools net-firewall/nftables
Create local host private and public keys:
wg genkey > /etc/wireguard/privatekey wg pubkey < /etc/wireguard/privatekey > /etc/wireguard/publickey
Configuration
Each WireGuard tunnel requires it's own configuration, usually called wg0, wg1…
So, create one file for each tunnel at /etc/wireguard/wg0.conf:
- wg0.conf
[Interface] PrivateKey = << local private key >> Address = 10.100.0.1/24 ListenPort = << my port >> [Peer] PublicKey = << remote end public key >> Endpoint = << peer public IP >>:<< peer port >> AllowedIPs = 10.100.0.2/24 # PersistentKeepAlive = 25
Where:
- You can have as many peers as you need to connect to the local host
- The PrivateKey is the local host private key
- The Address is the local host address on the tunnel subnetwork
- The ListenPort is the port on which the local host can be reached from the peers. This can be omitted if the local host is not reacheable from the peers, in this case the local hosts will connect to the peers.
- The PublicKey is the remote host public key
- The Endpoint is the peer public IP, omit if the peer cannot be reached from the local host, in this case the peers will connect to the localhost.
- The peer port is the ListenPort of the peer
- The AllowedIPs limits which hosts can send data to the local host, in case you have more than one machine connecting trough the peer
- The PersistentKeepAlive is usefull to help keep the tunnel connected by sending a keekalive e forcing a reconnection.
Each peer (host) connecting to the WireGuard tunnel will need one of these files. If you have two hosts (tipycal setup), assume that you need two wgX.conf files, one located on each host. These pair of configuration files will need to symmetrical to each other.
Link the startup scripts and set it to start on boot:
ln -s /etc/init.d/wg-quick /etc/init.d/wg-quick.wg0 rc-update add wg-quick.wg0 default
Port Forwarding
For more details in NFTables, see here.
I will assume that you have one internal host and one external host connected trough WireGuard tunnel, already setup like described above.
The goal is having port 2022 of the external server redirect to port 22 of the internal server torugh the WireGuard tunnel so that you can SSH inside your internal server from outside, seamlessly.
I assume your external server has an interface called enp1s0, it's WireGuard interface is wg0 and the WireGuard subnet mask is 10.100.0.0/24, with 10.100.0.2 being the external server and 10.100.0.1 the internal server.
What we need:
- A dedicated table called wg
- A prerouting chain to apply DNAT to incoming packes on port 2022 to the wg tunnel port 22
- A postrouting chain to ensure that all reply packets are properly SNAT back to outside
Create the wg table:
nft add table ip wg
Create the base chains:
nft 'add chain ip wg ssh-in { type nat hook prerouting priority -100 ; }' nft 'add chain ip wg ssh-out { type nat hook postrouting priority 100 ; }'
Create the in-bound rule (the counter rule is only for debugging, you can omit that rule):
nft 'add rule ip wg ssh-in iifname enp1s0 tcp dport 22 counter' nft 'add rule ip wg ssh-in iifname enp1s0 tmp dport 22 dnat to 10.100.0.1'
Create the SNAT return rule (the counter rule is only for debugging, you can omit that rule):
nft 'add rule ip wg ssh-out ip daddr 10.100.0.1 counter' nft 'add rule ip wg ssh-out ip daddr 10.100.0.1 masquerade'
This is the resulting NFTables setup:
nft list table wg table ip wg { chain ssh-in { type nat hook prerouting priority dstnat; policy accept; iifname "enp1s0" tcp dport 22 counter packets 5 bytes 300 iifname "enp1s0" tcp dport 22 dnat to 10.70.0.1 } chain ssh-out { type nat hook postrouting priority srcnat; policy accept; ip daddr 10.70.0.1 counter packets 4 bytes 240 ip daddr 10.70.0.1 masquerade } }
nft add ip wg prerouting 'dnat to tcp dport map { 2022 : 10.70.0.1 . 22 }'