summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2025-10-12 22:31:51 -0700
committerrtk0c <[email protected]>2025-10-12 22:31:51 -0700
commit552bcdc848c8a272fc834f8ab9560f203037bbf7 (patch)
treea432bec318c4a1d2a890e2262fee78dd34d9ddab
parent387e4eb5f31fcb8f9ae570b73a01634de672243e (diff)
Hand rolled ngrok on protonvpn: sshd section initial draft
-rw-r--r--content/blog/hand-rolled-ngrok-over-protonvpn.md97
1 files changed, 97 insertions, 0 deletions
diff --git a/content/blog/hand-rolled-ngrok-over-protonvpn.md b/content/blog/hand-rolled-ngrok-over-protonvpn.md
new file mode 100644
index 0000000..55168bd
--- /dev/null
+++ b/content/blog/hand-rolled-ngrok-over-protonvpn.md
@@ -0,0 +1,97 @@
+---
+title: "I paid for the whole vpn, so I'm damn well going to use the whole vpn"
+tags: ["sysadmin"]
+categories: ["Life of a sysadmin"]
+draft: true
+---
+
+_Or: hand roll a ngrok with protonvpn port forwarding, for shits and giggles_
+
+# Dumbness: port forward `sshd`
+
+Our general plan is this:
+Bring up a wireguard tunnel to protonvpn as usual.
+Bring up sshd as usual.
+Port forward some public port to `10.2.0.2:22`, with `natpmpc(1)`.
+
+The first two steps are just the standard issue procedure, I won't go over it here. I'll assume the wireguard config is placed at `/etc/wireguard/protonvpn.conf`, so bringing it up is simply `wg-quick up protonvpn`.
+Also remember to harden `sshd`, like disable password login and setup fail2ban. Otherwise you'll have a pretty bad day...
+
+First, the port forwarding logic.
+It's a simple bash script `/usr/local/bin/protonvpn-update-port-mapping`, adapted from [here](https://github.com/giu176/ProtonVPN-auto-NATPMP/blob/main/natpmpc_script.sh).
+
+```bash
+#!/bin/bash
+
+TMPFILE=/tmp/natpmpc_output
+
+# We can assume the exit node IP doesn't change
+ip=$(curl -s --interface=protonvpn -4 icanhazip.com)
+echo "$ip" > "$RUNTIME_DIRECTORY/public-ip"
+ip6=$(curl -s --interface=protonvpn -6 icanhazip.com)
+echo "$ip6" > "$RUNTIME_DIRECTORY/public-ip6"
+
+while true; do
+ natpmpc -a 1 22 udp 60 -g 10.2.0.1 > /dev/null \
+ && natpmpc -a 1 22 tcp 60 -g 10.2.0.1 > $TMPFILE \
+ || {
+ echo -e "ERROR with natpmpc command \a"
+ break
+ }
+
+ port=$(grep 'TCP' $TMPFILE | grep -o 'Mapped public port [0-9]*' | awk '{print $4}')
+ rm $TMPFILE
+
+ echo "$port" > "$RUNTIME_DIRECTORY/public-port"
+
+ sleep 45
+done
+```
+
+In the script provided in [protonvpn docs](https://protonvpn.com/support/port-forwarding-manual-setup), natpmpc is called with privateport = 0, which means use the same port as the public port, allocated by the gateway.
+Changing it to 22 makes it so that the gateway still chooses whatever it wants, but the privateport is always mapped to 22, on which sshd is listening.
+
+You'll notice we map UDP on line 12, in addition to TCP on line 13.
+Indeed it's not necessary for sshd, but I'm going to reference this same script in the wireguard section below, which does need UDP.
+
+Second, a systemd service `/etc/systemd/system/protonvpn-natpmp.service`.
+Note `[email protected]` is a template provided in the most linux distros just runs wg-quick on the pprovided config.
+And setting `RuntimeDirectory` will create the `$RUNTIME_DIRECTORY` env var used by the script above.
+
+```ini
+[Unit]
+Description=ProtonVPN NAT-PMP port forwarding update
+
+[Service]
+Type=exec
+ExecStart=/usr/local/bin/protonvpn-update-port-mapping
+
+RuntimeDirectory=protonvpn-natpmp
+
+# Harden, because why not
+ProtectSystem=strict
+PrivateTmp=true
+ProtectHome=true
+PrivateDevices=true
+ProtectKernelTunables=true
+ProtectControlGroups=true
+
+[Install]
+WantedBy=multi-user.target
+```
+
+Reload to pick up the new unit files.
+Enable and immediately start both services:
+
+```
+# systemctl daemon-reload
+# systemctl enable --now [email protected] protonvpn-natpmp.service
+```
+
+Read the public address under `/run/protonvpn`, now you should be able to ssh, from anywhere on the internet, to this machine.
+
+# Sillinessw: port forward wireguard
+
+TODO