OpenVPN has a feature called
In some instances you might want to have a better control over which clients can talk to which clients, and using
How to solve the problem? The answer is: do NOT use
To confirm that this is true, run tcpdump on the server while
server:~# tcpdump -v -n -i tun0 ... 15:31:13.265709 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84) 10.180.0.2 > 10.180.0.3: ICMP echo request, id 56579, seq 1, length 64 15:31:13.266836 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto ICMP (1), length 84) 10.180.0.2 > 10.180.0.3: ICMP echo request, id 56579, seq 1, length 64 15:31:13.269941 IP (tos 0x0, ttl 64, id 55097, offset 0, flags [none], proto ICMP (1), length 84) 10.180.0.3 > 10.180.0.2: ICMP echo reply, id 56579, seq 1, length 64 15:31:13.269964 IP (tos 0x0, ttl 63, id 55097, offset 0, flags [none], proto ICMP (1), length 84) 10.180.0.3 > 10.180.0.2: ICMP echo reply, id 56579, seq 1, length 64 15:31:14.286694 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84) 10.180.0.2 > 10.180.0.3: ICMP echo request, id 56579, seq 2, length 64 15:31:14.286728 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto ICMP (1), length 84) 10.180.0.2 > 10.180.0.3: ICMP echo request, id 56579, seq 2, length 64 15:31:14.290280 IP (tos 0x0, ttl 64, id 55098, offset 0, flags [none], proto ICMP (1), length 84) 10.180.0.3 > 10.180.0.2: ICMP echo reply, id 56579, seq 2, length 64 15:31:14.290301 IP (tos 0x0, ttl 63, id 55098, offset 0, flags [none], proto ICMP (1), length 84) 10.180.0.3 > 10.180.0.2: ICMP echo reply, id 56579, seq 2, length 64 ...
You see each packet twice (but note the decremented TTL), meaning that it really goes out and then back into tun0. This gives us a hook where we can insert suitable iptables rules in the FORWARD chain. For example, if clients are on the
# allow already established connections (listed first for efficiency) # iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT # allow communication between 10.180.0.2 and 10.180.0.8, only if initiated by 10.180.0.2 # iptables -A FORWARD -s 10.180.0.2 -d 10.180.0.8 -m conntrack --ctstate NEW -j ACCEPT # allow full communication between 10.180.0.4 and 10.180.0.11 # iptables -A FORWARD -s 10.180.0.4 -d 10.180.0.11 -j ACCEPT # iptables -A FORWARD -s 10.180.0.11 -d 10.180.0.4 -j ACCEPT # deny everything else # iptables -A FORWARD -j DROP # or set a default policy
This works fine; the only issue is a few extra packets are generated by the server. These are ICMP redirects that it sends to the clients when it sees that they are sending data to each other via the server instead of communicating directly since they are in the same "subnet". Of course, this is because the server does not really know what's going on, and the generation of these ICMP redirect packets for the tun interface can be turned off on the server by writing 0 into the two virtual files
send_redirects - BOOLEAN Send redirects, if router. send_redirects for the interface will be enabled if at least one of conf/{all,interface}/send_redirects is set to TRUE, it will be disabled otherwise Default: TRUE
So the other interfaces, having 1 in their specific file, will still send redirects.
All the above is applicable when running in routed mode only. If you're using bridged mode, there doesn't seem to be an easy method to control
Update 10/06/2010: it seems that it's possible to control client to client connections even in tap (bridged) mode, using OpenVPN's internal packet filter, although it's not straightforward. A future article will examine that.
Update 18/06/2010: the article is here.
Gracias, este articulo es exactamente lo que estaba buscado, excelente trabajo.
thanks, this article was exactly what I was looking for, great job
I know this entry is pretty old even so it helped me a lot configuring my vpn so that just selected client can talk to each other. most of them can only see one machine besides the server.
But I had problems which are not mentioned here:
1. I needed to enable ip forwarding (this may be obvious but I thought first it would word without because it is in the same network)
2. After removing "client-to-client" the clients had no routes for the other ips in the network anymore. I solved that by adding 'push "route 10.x.0.0 255.255.255.0"' into the openvpn server config. which seems to work. I am not sure if that is the right/best solution though.
1. Right, IP forwarding is not mentioned explicitly, although the fact that the TTL is decremented and that iptables rules are in the FORWARD chain should hint in that direction, but it's always better to be clear, so thanks for pointing that out.
2. This is a bit strange, "client-to-client" should have no effect on the routes that the client installs, which should be determined only by 'push "route ...."' statements in the server config and 'route ....' statements in the client config, at least when using "topology subnet" (which is what should be used anyway).
Hi Guys I have a OpenVPN server installed in bridged mode.
1/
When Clients connect I want them to not see the LAN at xxx.xxx.xxx.0/24 but only the VPN server at xxx.xxx.xxx.www which they will use for internet access. That is VPN clients must not be able to access regular LAN clients and regular LAN clients must not be able to access VPN connected clients.
2/
Additionally I have ssh and a webserver running on the OpenVPN Server, and would like to block these two ports from being accessed by the vpn clients which have a dhcp range of xxx.xxx.xxx.yyy - xxx.xxx.xxx.zzz.
Can someone tell me how to achieve this with some simple and concise rulesets.
Thanks.
So far I think I have accomplished 2/ but no cannot accomplish 1/ no matter what rule I try.
Here is what I have so far...
iptables -A INPUT -p udp --dport 1194 -j ACCEPT
iptables -A INPUT -p tcp -m iprange --src-range 172.25.26.90-172.25.26.99 --dst 172.25.26.252 --dport 22 -j DROP
iptables -A INPUT -p tcp -m iprange --src-range 172.25.26.90-172.25.26.99 --dst 172.25.26.252 --dport 80 -j DROP
iptables -A INPUT -m iprange --src-range 172.25.26.90-172.25.26.99 ! --dst 172.25.26.252 -j DROP
iptables -A INPUT -i tap0 -j ACCEPT
It's the fourth rule that I was trying to block the vpn clients from seeing each other and the regular lan clients, and vice versa.
I've disabled client-to-client by removing it from the server config file but strangely clients can still ping/see each other.
from the openvpn site...
# Uncomment this directive to allow different
# clients to be able to "see" each other.
# By default, clients will only see the server.
# To force clients to only see the server, you
# will also need to appropriately firewall the
# server's TUN/TAP interface.
;client-to-client
In bridged mode, iptables rules are ineffective. You have to use OpenVPN's built-in packet filtering capabilities, as explained in http://backreference.org/2010/06/18/openvpns-built-in-packet-filter/. If you read the comments, you'll see that there was a bug in OpenVPN, which was later fixed.
I suppose another option is messing around with ebtables, but I don't know how practical that would be (probably very little).
And anyway, what's the point of using bridged mode if the VPN clients should not be able to access the LAN? That's basically the main reason (or among the main reasons) for using bridged mode.
You are right there. I've thrown away bridge and had to learn how to do the routed method. Currently Everyone is able to ping everyone from vpn to lan, vpn to vpn and so on. I will fiddle around with the IPtables now to see how I can cordon off each client to it's own sandbox. I may be back for assistance If I can't figure it out if you don't mind.
Thanks.
What I am trying to achieve is
1/
blocking the vpn network from seeing the LAN,
2/
stop a vpn client from seeing another vpn client.
3/
Vpn clients can talk to the internet.
4/
LAN clients cannot see the vpn clients.
I've put together these rules. They are the ones I settled on after a number of combinations, and was sure they should work, I can't see why they don't as I am not achieving #3, only all the rest.
172.25.90.0 = VPN Network
iptables -A FORWARD --dst 172.25.90.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD --dst 10.0.0.0/8 -j DROP
iptables -A FORWARD --dst 172.16.0.0/12 -j DROP
iptables -A FORWARD --dst 192.168.0.0/16 -j DROP
iptables -A FORWARD --src 172.25.90.0/24 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -j DROP
For the VPN clients to reach the internet (I guess through your VPN gateway) you have to do a few things.
First, the VPN clients need to install a route (to the whole Internet or whatever) pointing to the VPN gateway. Depending on the route you want them to have, this can be achieved by pushing one or more specific routes to the clients, or directly pushing "redirect-gateway" (if you use this one, I suggest you also use the "def1" flag - the man has all the details). This is done by editing the VPN server config.
Second, you'll want to NAT the traffic received from the VPN calient and going to the Internet, so you need something like
iptables -t nat -A POSTROUTING -o eth1 -s 172.25.90.0/24 -j MASQUERADE
where eth1 is the Internet-facing interface on the VPN gateway. Of course, you'll also need to enable IP forwarding and allow this traffic in the FORWARD chain (if you're not doing it already).
See this page for some examples: http://community.openvpn.net/openvpn/wiki/BridgingAndRouting
Dinamtko, I think you are correct about adding the routes. Would these routes be added in the server.conf file and then pushed to the clients? Would I need to push all the routes in /30net topology or could they be summarized? Is is possible to push /30net routes to just a few select clients?
Like I had posted earlier, I found a work around with add another VPN. However, I am still wondering what the fix is. thx.
Darrell, when you use openvpn in server mode and disable client-to-client you have to manually add routes between the clients and then they will be able to ping themselves again, so you can filter them on the tunX interface.
I think (but I have not verified) that what you say is correct, but only when using the "point to point" or "net30" topology. If you use the "subnet" topology, clients should automatically have a route for the whole /24 or whatever client network pointing out the tun interface.
I will do further tests to check this.
To anyone finding this post.
I was not able to restrict clients using the posted method. Im not sure why, but it might have to-do with the fact my VPN(s) are running virtually in a OpenVZ container. However, I did find a work around. I created 3 VPNs (Family,Biz and Personal). My Personal VPN has access to everything, with no firewalls. The Family and Biz VPNs are heavily firewalled allowing mostly only traffic into the VPNs, but not out. This allows me to monitor and maintain the machines connected, without exposing my local network.
So I have three VPNs, running in OpenVZ containers under Proxmox, each using 30-40 megs of memory and almost 0 CPU. Priceless!
Im not trying to block 10.5.x.x > 10.5.x.x. Im try ping to allow it to a few select clients. I think I might have a routing issue. If I do a trace route 10.5.0.5 the path is out eth0 NOT tun0. This is a problem.
What option(s) in my server.conf file do I need, to tell my clients how to reach the entire 10.5.0.0 subnet? All my clients have static IPs. Each static IP is on it own /30 subnet (that makes 65 possible subnets). I believe this maybe what is causing my issue.
The blocking is not a issue, it's the pinging. I'm not able to ping between .21 and .58. I'm thinking it's a routing issue now. If I do a trace route 10.5.0.58 it routes out the Internet interface not the VPN. The server must not be pushing the correct route info down to the client. All the clients are on the /30 subnet as described in the openvpn how to. Some how think I need to advertise a route for all vpn clients that points to the VPN.
This article was exactly what I was looking for. However, I cant seem to make it work on my routed OpenVPN. Below is my iptables, do they look correct? Im trying to ping to&from 10.5.0.21 and 10.5.0.58 and block all other 10.5.x.x > 10.5.x.x. traffic.
Chain FORWARD (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state ESTABLISHED
ACCEPT all -- anywhere anywhere state RELATED
ACCEPT all -- 192.168.100.0/24 10.5.0.0/24
ACCEPT udp -- 10.5.0.0/24 192.168.100.0/24 udp spt:iax
ACCEPT tcp -- 10.5.0.58 mythtv tcp multiport ports ssh
ACCEPT all -- 10.5.0.21 10.5.0.58
ACCEPT all -- 10.5.0.58 10.5.0.21
DROP all -- 10.5.0.0/24 192.168.100.0/24
Thanks for posting this
Since you don't have a rule that explicitly blocks traffic from 10.5.xx to 10.5.xx, the default policy is used which is ACCEPT. I think you have to either change the default policy to DROP, or add another rule at the end that explicitly blocks traffic from 10.5.x.x to 10.5.x.x.