Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| gentoo:wireguard [2025/02/05 15:22] – [Port Forwarding] willy | gentoo:wireguard [2026/03/19 08:21] (current) – [Watchdog] willy | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== WireGuard ====== | + | ====== |
| - | [[https:// | + | [[https:// |
| + | |||
| + | WireGuard will create an encrypted and protected tunnel between hosts, where each host act as a peer. You need to have at least one host reachable from all the others, of course, but then WireGuard will create a common subnetwork on which all the hosts will see each other. | ||
| ===== Concepts ===== | ===== Concepts ===== | ||
| - | network | + | You should be fmailiar with basic networking concepts like routing, subnets, addresses. |
| + | |||
| + | A **subnet** is a portion of a network | ||
| + | |||
| + | All VPNs work by creating an encrypted **tunnel** between it's peers. This tunnel needs to be initiated from one host to the other (or viceversa) and whatever traffic flows inside the tunnes is not intellegible to anyone else because it's, guess what, encrypted. | ||
| - | tunnel | + | To perform the encryption at both ends, some encryption **keys** needs to be shared. The approach used by WireGuard is to use the private/ |
| - | keys | ||
| ===== Installation ===== | ===== Installation ===== | ||
| - | You will also need **nftables** if you plan to do port-forwarding | + | These steps need to be followed on every host that participate in the WireGuard tunnel. |
| + | |||
| + | Installing WireGuard on Gentoo is pretty easy since the latest release is always in portage, but you will also need [[gentoo: | ||
| <code bash> | <code bash> | ||
| emerge -v net-vpn/ | emerge -v net-vpn/ | ||
| </ | </ | ||
| + | |||
| Create local host private and public keys: | Create local host private and public keys: | ||
| Line 22: | Line 30: | ||
| wg genkey > / | wg genkey > / | ||
| wg pubkey < / | wg pubkey < / | ||
| + | chmod 500 / | ||
| </ | </ | ||
| + | |||
| + | You will need these two keys for the configuration below. | ||
| ===== Configuration ===== | ===== Configuration ===== | ||
| - | Each WireGuard tunnel | + | A WireGuard tunnel |
| - | So, create | + | So, create |
| <file - wg0.conf> | <file - wg0.conf> | ||
| [Interface] | [Interface] | ||
| - | PrivateKey = << local private key >> | + | PrivateKey = << local host private key >> |
| Address = 10.100.0.1/ | Address = 10.100.0.1/ | ||
| - | ListenPort = << | + | ListenPort = << |
| [Peer] | [Peer] | ||
| - | PublicKey = << remote | + | PublicKey = << remote |
| - | Endpoint = << | + | Endpoint = << |
| - | AllowedIPs = 10.100.0.2/ | + | AllowedIPs = 10.100.0.2/ |
| PersistentKeepAlive = 25 | PersistentKeepAlive = 25 | ||
| </ | </ | ||
| Where: | Where: | ||
| - | * You can have as many peers as you need to connect to the local host | + | * You can have as many peers as you need to connect to the local host, just create one [Peer] block for each one. |
| * The // | * The // | ||
| - | * The //Address// is the __local host__ address on the tunnel subnetwork | + | * The //Address// is the __local host__ address on the __tunnel subnetwork__ (usually, a new subnet you are not using already) |
| - | * The // | + | * The // |
| * The // | * The // | ||
| - | * The // | + | * The // |
| - | * The //peer port// is the // | + | * The // |
| - | * The // | + | |
| * The // | * The // | ||
| - | 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 // | + | Each host connecting to the WireGuard tunnel will need one of these files. These configuration files should usually be symmetrical to each other. |
| Link the startup scripts and set it to start on boot: | Link the startup scripts and set it to start on boot: | ||
| Line 61: | Line 71: | ||
| </ | </ | ||
| - | ===== Port Forwarding | + | ===== Watchdog |
| - | For more details in NFTables, see [[[[gentoo: | + | In my experience, when the main router reboots or the internet connection is switched, the wireguard tunnel might hang up for a very long time. I am not sure why this happen, it shouldn' |
| - | I will assume | + | To ensure this doesn' |
| + | <file - tunnel-watchdog> | ||
| + | # | ||
| - | 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. | + | description=" |
| - | 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. | + | # The services you want to restart |
| + | SERVICES=" | ||
| + | PING_HOST=" | ||
| + | LOG="/ | ||
| + | FAIL_COUNT_LIMIT=5 | ||
| + | PING_TIMEOUT=1 | ||
| + | PING_COUNT=1 | ||
| - | What we need: | + | restart_service() { |
| - | * A dedicated table called **wg** | + | for i in ${SERVICES} |
| - | * A **prerouting** chain to apply DNAT to incoming packes on port 2022 to the wg tunnel port 22 | + | do |
| - | * A **postrouting** chain to ensure that all reply packets are properly SNAT back to outside | + | einfo " |
| + | / | ||
| + | done | ||
| + | } | ||
| - | Create the wg table: | + | depend() { |
| - | <code bash> | + | need net |
| - | nft add table ip wg | + | } |
| - | </ | + | |
| - | Create | + | start() { |
| + | ebegin " | ||
| + | echo $(date)" | ||
| + | while : ; do | ||
| + | # Perform a quick ping. -q quiet, -c N packets, -W T timeout | ||
| + | if ! ping -q -c ${PING_COUNT} -W ${PING_TIMEOUT} ${PING_HOST} >/ | ||
| + | fail_count=$((fail_count + 1)) | ||
| + | echo $(date)" | ||
| + | else | ||
| + | fail_count=0 | ||
| + | fi | ||
| + | |||
| + | # If we hit the threshold, restart | ||
| + | if [ " | ||
| + | echo $(date)" | ||
| + | restart_service | ||
| + | fail_count=0 | ||
| + | fi | ||
| + | |||
| + | # Wait a bit before the next check | ||
| + | sleep 5 | ||
| + | done & | ||
| + | PID=$! | ||
| + | echo ${PID} > / | ||
| + | eend 0 | ||
| + | } | ||
| + | |||
| + | stop() { | ||
| + | ebegin " | ||
| + | if [ -f / | ||
| + | PID=$(cat / | ||
| + | kill -9 " | ||
| + | rm / | ||
| + | else | ||
| + | eend 255 | ||
| + | fi | ||
| + | eend 0 | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Now make it executable add to the runlevel default and start it: | ||
| <code bash> | <code bash> | ||
| - | nft 'add chain ip wg ssh-in { type nat hook prerouting priority -100 ; }' | + | chmod +x / |
| - | nft 'add chain ip wg ssh-out { type nat hook postrouting priority 100 ; }' | + | rc-update |
| + | / | ||
| </ | </ | ||
| - | Create the SNAT return rule: | + | As a final note, don't forget to put log file **/ |
| - | <code bash> | + | |
| + | |||
| + | ===== Remote access ===== | ||
| - | nft add rule ip wg prerouting tcp dport 2022 dnat to 10.70.0.1 dport 22 | + | There are tons of WireGuard tutorials online on how to use WireGuard |
| - | nft add rule ip wg prerouting tcp dport 22 dnat to 10.70.0.1 | + | |
| - | nft add rule ip wg postrouting ip daddr 10.70.0.1 masquerade | ||
| - | nft add ip wg prerouting 'dnat to tcp dport map { 2022 : 10.70.0.1 . 22 }' | ||