I have a server with Pi-Hole configured to block Ads and trackers. The clients are connected via OpenVPN and get addresses from 10.8.0.0/24. OpenVPN only pushes the DNS to the client and the traffic is routed via the local gateway but of course, every client on the VPN can contact every other client via their 10.8.0.x addresses.
I have ordered a second ipv4 that I would like to use specifically for the client 10.8.0.4. I want to be able to access the public ip and expose that client directly to the internet to use a locally hosted Nextcloud.
I searched Server Fault and found some similar problems. I tried to add POSTROUTING and PREROUTING rules to iptables but that didn't work out. The ipv4 is currently added temporarily to eth0 via 'ip addr add xx.xx.xx.xx. dev eth0', not tun0 (is that correct?). The OpenVPN Server is configured exactly as mentioned in the Pi-Hole docs (https://docs.pi-hole.net/guides/vpn/openvpn/only-dns-via-vpn/). net.ipv4.ip_forward is enabled.
Do I even have to use iptables? Is it possible or advised to add the public ip to a route or something? Sorry if the question sounds silly. I'm pretty new to OpenVPN and Route/iptables configuration.
That is the first thing I tried: Redirect all incoming traffic from a secondary public IP to an internal IP address using iptables
My current iptables rules are:
# Generated by xtables-save v1.8.2 on Thu Dec 12 14:37:26 2019
*nat
:PREROUTING ACCEPT [329:28209]
:INPUT ACCEPT [281:25114]
:POSTROUTING ACCEPT [17:1423]
:OUTPUT ACCEPT [245:22126]
-A POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to-source xx.xx.xx.xx
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT
# Completed on Thu Dec 12 14:37:26 2019
# Generated by xtables-save v1.8.2 on Thu Dec 12 14:37:26 2019
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i tun0 -j ACCEPT
-A INPUT -i tun0 -p tcp -m tcp --dport 53 -j ACCEPT
-A INPUT -i tun0 -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -i tun0 -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -i tun0 -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 2202 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 1194 -j ACCEPT
-A INPUT -p udp -m udp --dport 1194 -j ACCEPT
-A INPUT -p udp -m udp --dport 80 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p udp -m udp --dport 443 -j REJECT --reject-with icmp-port-unreachable
COMMIT
# Completed on Thu Dec 12 14:37:26 2019
iptables NAT rules:
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
SNAT all -- 10.8.0.0/24 !10.8.0.0/24 to:xx.xx.xx.xx
MASQUERADE all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
After the comment from NiKiZe i added the public ip address temporarily via
ip addr add xx.xx.xx.xx dev eth0
and entered both rules (to clarify that: i exported the working ruleset via iptables-save, edited both commands in and restored it via iptables-restore)
-A PREROUTING -d xx.xx.xx.xx -j DNAT --to-destination 10.8.0.4
-A POSTROUTING -s 10.8.0.4 ! -d 10.8.0.4 -j SNAT --to-source xx.xx.xx.xx
I then opened several terminal sessions and monitored the web traffic with tcpdump at the OpenVPN server and my local server, confirming that incoming traffic at eth0 to pi.hole.http is routed to my local server server.vpn.http correctly. But the answer times out...
My current nat rules are:
user@dns:~# iptables -t nat -vL --line-numbers
Chain PREROUTING (policy ACCEPT 1 packets, 52 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 DNAT all -- any any anywhere pi.hole to:10.8.0.4
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 1 packets, 60 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 SNAT all -- any any server.vpn !server.vpn to:xx.xx.xx.xx <- temporarily added ip address
2 0 0 SNAT all -- any any 10.8.0.0/24 !10.8.0.0/24 to:xx.xx.xx.xx <- main ip address, statically entered
3 0 0 MASQUERADE all -- any eth0 anywhere anywhere
Chain OUTPUT (policy ACCEPT 1 packets, 60 bytes)
num pkts bytes target prot opt in out source destination
Another edit:
When i add 'src server.vpn' to tcpdump i can see that there is no outbound traffic from the local server. So there has to be either a problem with the local server configuration or the postrouting rule. Am i correct?
After changing the route on the server.vpn the connection is working.
'route -n' Before:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.178.1 0.0.0.0 UG 0 0 0 eth0
10.8.0.0 0.0.0.0 255.255.255.0 U 0 0 0 tun0
169.254.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth3
169.254.160.0 169.254.160.1 255.255.248.0 UG 0 0 0 tun1000
169.254.160.0 0.0.0.0 255.255.248.0 U 0 0 0 tun1000
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.178.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
And after:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.8.0.1 0.0.0.0 UG 0 0 0 tun0
10.8.0.0 0.0.0.0 255.255.255.0 U 0 0 0 tun0
169.254.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth3
169.254.160.0 169.254.160.1 255.255.248.0 UG 0 0 0 tun1000
169.254.160.0 0.0.0.0 255.255.248.0 U 0 0 0 tun1000
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.178.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
If i understand this correctly, that means that EVERY network connection, even initiated by server.vpn is routed via the VPN. This is not the anticipated behavior. I simply want the server to be accessible locally and use the regular, locally routed internet and also answer connections routed from the public ip on the OpenVPN Server.