Users reaching each other
Whether VPN users can reach each other is decided by one option, client-to-client, and it matters more than it looks, because it changes who enforces the rules.
Without it (the default), traffic from one user to another goes up into the server's kernel through tun0, gets routed, and goes back out of tun0. Like any routed traffic, it passes through the server's firewall, which in this lab drops it: alice can reach neither bob nor the branch LAN, and the firewall's counter shows every dropped packet.
With it, OpenVPN delivers user-to-user traffic itself, inside the server process, and never hands it to the kernel. alice reaches bob and the branch LAN at once, but look at the firewall counter: unchanged. The firewall never saw that traffic, so no rule you write there can control it.
Which to choose:
- Users should be isolated (most remote-access VPNs): leave
client-to-clientoff, and the firewall stays in charge. - Some users should reach each other, or a branch LAN: still leave it off, and add specific forward rules from
tun0totun0for exactly what's allowed. You keep control and a record. - Everyone may reach everyone (a small, trusted team):
client-to-clientis simple, as long as you know your firewall can no longer see that traffic.
The lab goes back to the default for the rest of the lesson.
root@alice:~# ping -c 3 -W 1 10.8.0.11
PING 10.8.0.11 (10.8.0.11) 56(84) bytes of data.
--- 10.8.0.11 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2040ms
root@alice:~# ping -c 2 -W 1 10.20.0.10
PING 10.20.0.10 (10.20.0.10) 56(84) bytes of data.
--- 10.20.0.10 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1024ms
root@vpn:~# nft list chain inet filter forward | grep -E "counter|policy"
type filter hook forward priority filter; policy drop;
counter packets 9 bytes 756 comment "everything else, including user to user, is dropped"- Lines 1–5: alice to bob: dropped.
- Lines 8–12: alice to the branch LAN: dropped.
- Line 17: The firewall counted them.
root@vpn:~# echo client-to-client >> /etc/openvpn/server/server.conf && systemctl restart openvpn-server@server
root@vpn:~# cat /run/openvpn-server/status-server.log | grep CLIENT_LIST
HEADER,CLIENT_LIST,Common Name,Real Address,Virtual Address,Virtual IPv6 Address,Bytes Received,Bytes Sent,Connected Since,Connected Since (time_t),Username,Client ID,Peer ID,Data Channel Cipher
CLIENT_LIST,branch,198.51.100.23:33250,10.8.0.20,,4619,4736,2026-10-21 05:20:04,1792560004,UNDEF,1,1,AES-256-GCM
CLIENT_LIST,bob,198.51.100.22:55509,10.8.0.11,,4613,4766,2026-10-21 05:20:04,1792560004,UNDEF,2,2,AES-256-GCM
CLIENT_LIST,alice,198.51.100.21:49952,10.8.0.10,,4617,4766,2026-10-21 05:20:04,1792560004,UNDEF,0,0,AES-256-GCM
root@alice:~# ping -c 3 -W 1 10.8.0.11
PING 10.8.0.11 (10.8.0.11) 56(84) bytes of data.
64 bytes from 10.8.0.11: icmp_seq=1 ttl=64 time=0.360 ms
64 bytes from 10.8.0.11: icmp_seq=2 ttl=64 time=0.812 ms
64 bytes from 10.8.0.11: icmp_seq=3 ttl=64 time=2.84 ms
--- 10.8.0.11 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2032ms
rtt min/avg/max/mdev = 0.360/1.338/2.844/1.080 ms
root@alice:~# ping -c 2 -W 1 10.20.0.10
PING 10.20.0.10 (10.20.0.10) 56(84) bytes of data.
64 bytes from 10.20.0.10: icmp_seq=1 ttl=63 time=0.473 ms
64 bytes from 10.20.0.10: icmp_seq=2 ttl=63 time=2.82 ms
--- 10.20.0.10 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1065ms
rtt min/avg/max/mdev = 0.473/1.647/2.821/1.174 ms
root@vpn:~# nft list chain inet filter forward | grep -E "counter|policy"
type filter hook forward priority filter; policy drop;
counter packets 9 bytes 756 comment "everything else, including user to user, is dropped"- Line 1: One line in server.conf, then a restart. Users reconnect by themselves.
- Lines 9–17: alice reaches bob…
- Lines 19–26: …and the branch LAN.
- Line 30: The firewall counter hasn't moved: it never saw this traffic, so no firewall rule can control it.
Check your understanding
With client-to-client enabled, you add an nftables rule on the VPN server to stop bob reaching alice. bob can still reach alice. Why?
- With client-to-client, OpenVPN forwards user-to-user traffic itself, so it never passes through the kernel's firewall.
- nftables rules only apply after a reboot.
- bob's certificate overrides the firewall.
- The rule needs to be in the input chain.