Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| gentoo:wireguard [2025/02/06 07:16] – willy | gentoo:wireguard [2026/03/19 08:21] (current) – [Watchdog] willy | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== WireGuard ====== | + | ====== |
| [[https:// | [[https:// | ||
| Line 71: | Line 71: | ||
| </ | </ | ||
| - | ===== Remote access | + | ===== Watchdog |
| - | There are tons of WireGuard tutorials online on how to use WireGuard to connect your mobile device securely to your home network, i do not plan to cover this topic here. | + | 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' |
| + | To ensure this doesn' | ||
| + | <file - tunnel-watchdog> | ||
| + | # | ||
| - | ===== Port Forwarding ===== | + | description=" |
| - | Using WireGuard for port-forwarding between an external, public accessible host, and an internal non-accessible host (like behind a CGNAT) is a less known topic and i will cover it here. | + | # The services you want to restart |
| + | SERVICES=" | ||
| + | PING_HOST=" | ||
| + | LOG="/ | ||
| + | FAIL_COUNT_LIMIT=5 | ||
| + | PING_TIMEOUT=1 | ||
| + | PING_COUNT=1 | ||
| - | You will need to use NFTables, see [[[[gentoo: | + | restart_service() { |
| + | | ||
| + | do | ||
| + | einfo " | ||
| + | /etc/init.d/$i restart | ||
| + | done | ||
| + | } | ||
| - | Assumptions: | + | depend() { |
| - | * You have one **internal** host which is behind CGNAT, and is not accessible from the internet | + | need net |
| - | * You have one **external** host which has a public IP address | + | } |
| - | * Both hosts have WireGuard setup according to the configuration above | + | |
| - | * Internal host expose port 22, 80 and 8443 | + | |
| - | * External host needs to route those three ports to the internal host | + | |
| - | * The WireGuard subnet is // | + | |
| - | * External host **public** network interface is called **enp1s0** | + | |
| - | * Both hosts WireGuard network iunterface is called **wg0** | + | |
| - | What we need to do is create nftable rules to ensure that: | + | start() { |
| - | | + | ebegin " |
| - | * packets reaching external host on enp1s0 on port 80 get routed to 10.100.0.1 port 80 | + | echo $(date)" |
| - | * packets reaching external host on enp1s0 on port 443 get routed | + | while : ; do |
| - | * return packets from the internal host get properly re-routed to the original sender out from enp1s0 | + | # Perform a quick ping. -q quiet, -c N packets, -W T timeout |
| + | if ! ping -q -c ${PING_COUNT} -W ${PING_TIMEOUT} ${PING_HOST} >/ | ||
| + | | ||
| + | echo $(date)" | ||
| + | else | ||
| + | fail_count=0 | ||
| + | fi | ||
| - | **Note:** see [[selfhost:nginx|here]] on why i use port 8443 instead of port 443 on the internal server. This is to differentiate // | + | # If we hit the threshold, restart |
| + | if [ " | ||
| + | echo $(date)" | ||
| + | restart_service | ||
| + | fail_count=0 | ||
| + | fi | ||
| - | What we need: | + | # Wait a bit before the next check |
| - | * A dedicated table called **wg** | + | sleep 5 |
| - | * A **prerouting** chain to apply DNAT to incoming packes | + | done & |
| - | * Rules to route port 2022/80/443 to the wg tunnel | + | |
| - | * A **postrouting** chain to ensure that all reply packets are properly SNAT back to outside | + | echo ${PID} > /var/run/tunnel-watchdog.pid |
| - | * Return masquerading rules to ensure the return packets get sent back out of enp1s0 | + | eend 0 |
| + | } | ||
| - | Create the wg table: | + | stop() { |
| - | <code bash> | + | |
| - | nft add table ip wg | + | if [ -f / |
| - | </code> | + | PID=$(cat / |
| + | kill -9 " | ||
| + | rm / | ||
| + | else | ||
| + | eend 255 | ||
| + | fi | ||
| + | eend 0 | ||
| + | } | ||
| + | </file> | ||
| - | Create | + | Now make it executable add to the runlevel default and start it: |
| <code bash> | <code bash> | ||
| - | nft 'add chain ip wg prerouting { type nat hook prerouting priority | + | chmod +x / |
| - | nft 'add chain ip wg postrouting { type nat hook postrouting priority 100 ; }' | + | rc-update |
| + | / | ||
| </ | </ | ||
| - | Create the in-bound rules: | + | As a final note, don't forget |
| - | <code bash> | + | |
| - | nft 'add rule ip wg ssh-in iifname enp1s0 dnat to tcp dport map { 2022 : 10.100.0.1 . 22 }' | + | |
| - | nft 'add rule ip wg ssh-in iifname enp1s0 dnat to tcp dport map { 80 : 10.100.0.1 . 80 }' | + | |
| - | nft 'add rule ip wg ssh-in iifname enp1s0 dnat to tcp dport map { 443 : 10.100.0.1 . 8443 }' | + | |
| - | </code> | + | |
| - | + | ||
| - | Create the SNAT return rule (the counter rule is only for debugging, you can omit that rule): | + | |
| - | <code bash> | + | |
| - | 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: | + | |
| - | <code bash> | + | |
| - | nft list table wg | + | |
| - | table ip wg { | + | |
| - | chain ssh-in { | + | |
| - | type nat hook prerouting priority dstnat; policy accept; | + | |
| - | iifname " | + | |
| - | iifname " | + | |
| - | } | + | |
| - | + | ||
| - | chain ssh-out { | + | |
| - | type nat hook postrouting priority srcnat; policy accept; | + | |
| - | ip daddr 10.100.0.1 counter packets 36 bytes 2140 | + | |
| - | ip daddr 10.100.0.1 masquerade | + | |
| - | } | + | |
| - | } | + | |
| - | </ | + | |
| - | + | ||
| - | nft add ip wg prerouting 'dnat to tcp dport map { 2022 : 10.70.0.1 . 22 }' | + | |
| + | ===== Remote access ===== | ||
| + | There are tons of WireGuard tutorials online on how to use WireGuard to connect your mobile device securely to your home network, i do not plan to cover this topic here. | ||