Allow client to client communication in OpenVPN for certain IP range

The Goal

We've got one OpenVPN Server that's up and running (10.8.0.0/16). And some clients. Clients can be separated into two specific groups: humans and non-humans. The non-humans shall only have access to the VPN server and a couple of external IP addresses through the VPN. The humans on the other hand shall have access to everything - especially to the non-humans (non-human clients have a web interface the humans shall reach).

What works

Humans and non-humans can connect to the VPN. Non-human access is successfully restricted.

The Problem

When connected with a human client, I cannot ping the non-human client nor can I reach the web interface of the non-human client.

~ ping 10.8.0.2
PING 10.8.0.2 (10.8.0.2) 56(84) bytes of data.
From 10.8.0.1 icmp_seq=2 Redirect Host(New nexthop: 2.0.8.10)
From 10.8.0.1 icmp_seq=3 Redirect Host(New nexthop: 2.0.8.10)
From 10.8.0.1 icmp_seq=4 Redirect Host(New nexthop: 2.0.8.10)

Configs

server.conf

local 192.168.12.152
port 1194
proto udp
dev tun0
ca ca.crt
cert server.crt
key server.key
dh dh.pem
auth SHA512
tls-crypt tc.key
topology subnet
server 10.8.0.0 255.255.0.0
client-config-dir /etc/openvpn/ccd
push "redirect-gateway def1 bypass-dhcp"
ifconfig-pool-persist ipp.txt
push "dhcp-option DNS 1.1.1.1"
push "dhcp-option DNS 8.8.8.8"
keepalive 10 120
cipher AES-256-CBC
user nobody
group nogroup
persist-key
persist-tun
status openvpn-status.log
verb 3
crl-verify crl.pem
explicit-exit-notify
management 127.0.0.1 5555

sample_client.ovpn (The Difference between humans and non-humans is made by ccd where clients get a static IP-address. Humans get a IP address from 10.8.255.0/24 and non-humans from 10.8.x.y [x != 255] - so in the ccd there is just 'ifconfig-push 10.8.y.y 255.255.0.0').

client
dev tun
proto udp
remote some-vpn-dyndns.net 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
auth SHA512
cipher AES-256-CBC
ignore-unknown-option block-outside-dns
block-outside-dns
verb 3
<ca>[...]</ca>
<cert>[...]</cert>
<key>[...]</key>
<tls-crypt>[...]</tls-crypt>

Iptable changes:

iptables -t nat -A POSTROUTING -s 10.8.0.0/16 ! -d 10.8.0.0/16 -j SNAT --to 192.168.12.152
iptables -I INPUT -p udp --dport 1194 -j ACCEPT
iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD -s 10.8.0.0/16 -j DROP
iptables -I FORWARD -s 10.8.0.0/16 -d 1.1.1.1 -j ACCEPT <---for DNS
iptables -I FORWARD -s 10.8.0.0/16 -d 8.8.8.8 -j ACCEPT <---for DNS
iptables -I FORWARD -s 10.8.0.0/16 -d 213.187.93.146 -j ACCEPT <--- special (dummy) server that non-humans have to reach
iptables -I FORWARD -s 10.8.255.0/24 -j ACCEPT

This adds to this iptables -L:

Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:1194
Chain FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 10.8.255.0/24 0.0.0.0/0
ACCEPT all -- 10.8.0.0/16 213.187.93.146
ACCEPT all -- 10.8.0.0/16 8.8.8.8
ACCEPT all -- 10.8.0.0/16 1.1.1.1
DROP all -- 10.8.0.0/16 0.0.0.0/0
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 

tl;dr If somebody could tell me why I'm not able to ping from a human client (10.8.255.1) a non-human client (10.8.0.2) - that would be really nice. (Everything else is working as it should)

Thanks in advance!

1 Answer

So I found a solution that kinda works.

What did I do? I changed some FORWARD rules.

Chain FORWARD (policy DROP)
target prot opt source destination
ACCEPT all -- 10.8.255.0/24 anywhere
ACCEPT all -- 10.8.0.0/16 some-dummy-server
ACCEPT all -- 10.8.0.0/16 dns.google
ACCEPT all -- 10.8.0.0/16 one.one.one.one
ACCEPT all -- one.one.one.one 10.8.0.0/16
ACCEPT all -- dns.google 10.8.0.0/16
ACCEPT all -- some-dummy-server 10.8.0.0/16
ACCEPT all -- anywhere 10.8.255.0/24 

First: the default policy for FORWARD is set to DROP. Second: allowed communication to default DNS-Servers for all of my VPN-Range, allowed communication to my special dummy server. Third: I allowed communication with everything and from everything with the IP range of my human clients.

Why do I say it kinda works? Because if I ping from a human client a non human client I still get this:

~ ping 10.8.0.2
PING 10.8.0.2 (10.8.0.2) 56(84) bytes of data.
64 bytes from 10.8.0.2: icmp_seq=1 ttl=63 time=120 ms
From 10.8.0.1 icmp_seq=2 Redirect Host(New nexthop: 2.0.8.10)
64 bytes from 10.8.0.2: icmp_seq=2 ttl=63 time=132 ms
From 10.8.0.1 icmp_seq=3 Redirect Host(New nexthop: 2.0.8.10)
64 bytes from 10.8.0.2: icmp_seq=3 ttl=63 time=108 ms
From 10.8.0.1 icmp_seq=4 Redirect Host(New nexthop: 2.0.8.10)
64 bytes from 10.8.0.2: icmp_seq=4 ttl=63 time=102 ms

I would guess that is because of the routing table on my (human) client side:

~ sudo route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default _gateway 0.0.0.0 UG 50 0 0 tun0
default _gateway 0.0.0.0 UG 600 0 0 wlp0s20f3
10.8.0.0 0.0.0.0 255.255.0.0 U 50 0 0 tun0
ip5b426419.dyna _gateway 255.255.255.255 UGH 600 0 0 wlp0s20f3
link-local 0.0.0.0 255.255.0.0 U 1000 0 0 wlp0s20f3
192.168.42.0 0.0.0.0 255.255.255.0 U 600 0 0 wlp0s20f3
_gateway 0.0.0.0 255.255.255.255 UH 600 0 0 wlp0s20f3

So if someone got a better idea, I'm happy to mark their answer as correct.

Ty for reading.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like