Blame
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 1 | # Fix for site-to-site OpenVPN on ubiquiti unifi routers |
| 2 | ||||
| 0859bc | Krzee | 2025-11-13 19:12:34 | 3 | # Background |
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 4 | I found that ubiquiti unifi routers break site-to-site by always using the [nathack](https://community.openvpn.net/Pages/NatHack) on the client side network. I got my hands on one and made a workaround which I am documenting here. |
| 5 | ||||
| 0859bc | Krzee | 2025-11-13 19:12:34 | 6 | # The problem |
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 7 | All traffic from the lan to a target over the VPN gets nat’ed to the IP of the vpn client on the router. Even after I fixed that it was also not forwarding traffic from the VPN to the LAN. |
| 8 | ||||
| 0859bc | Krzee | 2025-11-13 19:12:34 | 9 | # The fix |
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 10 | I was able to find the rule that causes the NAT and I was able to find where to insert a rule to allow forwarding from VPN to lan. The harder part was persistence. iptables rules do not persist a reboot, or even an openvpn reconnection. I found a directory named /data/ that can persist my scripts. I found that crontab works but does not persist reboots. I found that if I manually add a service it DOES persist reboots. By chaining this information together I was able to build a persistent fix for this router. |
| 11 | ||||
| 0859bc | Krzee | 2025-11-13 19:12:34 | 12 | # How to fix |
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 13 | |
| 14 | On the router enable sshd and log in as root to the router over sshd. |
|||
| cc9311 | Krzee | 2025-11-13 19:15:13 | 15 | |
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 16 | run: |
| 0859bc | Krzee | 2025-11-13 19:12:34 | 17 | |
| 18 | ``` |
|||
| 19 | mkdir /data/openvpn` |
|||
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 20 | vi /data/openvpn/undo_nathack.sh |
| 0859bc | Krzee | 2025-11-13 19:12:34 | 21 | ``` |
| 22 | ||||
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 23 | type i to enter insert mode and paste this: |
| 24 | ||||
| 0859bc | Krzee | 2025-11-13 19:12:34 | 25 | ``` |
| 26 | #!/bin/bash |
|||
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 27 | if /usr/sbin/iptables-save | /bin/grep tunovpn | /bin/grep -q MASQUERADE ;then |
| 28 | /usr/sbin/iptables-save | /bin/grep tunovpn | /bin/grep MASQUERADE | /bin/sed -e "s,-A,-D," | /usr/bin/awk '{system("/usr/sbin/iptables -t nat "$0)}' |
|||
| 29 | fi |
|||
| 30 | ! /usr/sbin/iptables-save | /bin/grep -q 'FORWARD -i tunovpnc' && /usr/sbin/iptables -I FORWARD -i tunovpnc+ -j ACCEPT |
|||
| 0859bc | Krzee | 2025-11-13 19:12:34 | 31 | ``` |
| 32 | ||||
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 33 | hit ESCAPE then type :x to save and exit vi |
| cc9311 | Krzee | 2025-11-13 19:15:13 | 34 | |
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 35 | run: |
| 0859bc | Krzee | 2025-11-13 19:12:34 | 36 | |
| 37 | `vi /data/openvpn/install_cron.sh` |
|||
| 38 | ||||
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 39 | type i to enter insert mode and paste this: |
| 40 | ||||
| 0859bc | Krzee | 2025-11-13 19:12:34 | 41 | ``` |
| 42 | #!/bin/sh |
|||
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 43 | CRON_COMMAND="/bin/sh /data/openvpn/undo_nathack.sh" |
| 44 | (crontab -l 2>/dev/null | grep -v "$CRON_COMMAND"; echo "* * * * * $CRON_COMMAND > /dev/null 2>&1") | crontab - |
|||
| 0859bc | Krzee | 2025-11-13 19:12:34 | 45 | ``` |
| 46 | ||||
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 47 | hit ESCAPE then type :x to save and exit vi |
| cc9311 | Krzee | 2025-11-13 19:15:13 | 48 | |
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 49 | run: |
| 0859bc | Krzee | 2025-11-13 19:12:34 | 50 | |
| 51 | `vi /etc/systemd/system/fix-vpn.service` |
|||
| 52 | ||||
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 53 | type i to enter insert mode and paste this: |
| 54 | ||||
| 0859bc | Krzee | 2025-11-13 19:12:34 | 55 | ``` |
| 56 | [Unit] |
|||
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 57 | Description=Fix unifi site-to-site VPN |
| 58 | Wants=network-online.target |
|||
| 59 | After=network-online.target |
|||
| 60 | ||||
| 61 | [Service] |
|||
| 62 | Type=oneshot |
|||
| 63 | User=root |
|||
| 64 | ExecStart=/bin/sh /data/openvpn/install_cron.sh |
|||
| 65 | ||||
| 66 | [Install] |
|||
| 67 | WantedBy=multi-user.target |
|||
| 0859bc | Krzee | 2025-11-13 19:12:34 | 68 | ``` |
| 69 | ||||
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 70 | hit ESCAPE then type :x to save and exit vi |
| cc9311 | Krzee | 2025-11-13 19:15:13 | 71 | |
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 72 | run: |
| 0859bc | Krzee | 2025-11-13 19:12:34 | 73 | |
| 74 | ```systemctl daemon-reload |
|||
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 75 | chmod +x /data/openvpn/install_cron.sh |
| 76 | chmod +x /data/openvpn/undo_nathack.sh |
|||
| 77 | systemctl enable fix-vpn.service |
|||
| 78 | systemctl start custom-vpn-nat.service |
|||
| 0859bc | Krzee | 2025-11-13 19:12:34 | 79 | ``` |
| 80 | ||||
| a8ec6f | Krzee | 2025-11-13 19:06:56 | 81 | Now you may turn off ssh in the router if you wish. |
