13

Setup: I have the an openvpn client/server setup (config files at bottom), and I get the infamous MULTI: bad source address from client [192.168.x.x], packet dropped message at server. The server has a public IP address, while the client is behind NAT.

Shortcomings of previously proposed solutions: The client-config-dir defined in the server config is currently empty. Previous posts (here and in openvpn support forums) suggest adding either a file named DEFAULT with the proper rules in client-config-dir, or adding a per-user file with those rules to solve the problem.

However, this doesn't seem to be a long-term solution, because these rules are client-location specific. So, I can add a rule to allow clients from 192.168.x.0 to connect. But if they connect from another network which instead uses 192.168.y.0 for NAT, a new rule will be required.

Questions:

  • Can the required rules be written in a generic/one-off way?
  • Can someone explain why this problem occurs in the first place?

Server config:

port 1234
proto tcp
dev tun

ca ca.crt
cert openvpn.crt
key openvpn.key
dh dh2048.pem

server 10.78.96.0 255.255.255.0
keepalive 10 120
comp-lzo
cipher CAMELLIA-128-CBC

user nobody
group nogroup  
persist-key
persist-tun
client-cert-not-required
plugin /usr/lib/openvpn/openvpn-auth-pam.so login

status openvpn-status.log

push "redirect-gateway def1"
push "remote-gateway 1.2.3.4"
push "dhcp-option DNS 8.8.8.8"

client-config-dir ccd
verb 4

Client config:

ca ca.crt
client
dev tun
proto tcp
remote 1.2.3.4 1234

auth-user-pass
script-security 2
keepalive 5 60
topology subnet
resolv-retry infinite
nobind
persist-key
persist-tun
ns-cert-type server
cipher CAMELLIA-128-CBC
comp-lzo
verb 4
m000
  • 440
  • 1
  • 4
  • 11
  • Are all of your clients on 192.168.x.y networks? – IceMage May 29 '15 at 20:16
  • It is not clear to me...Do you mean you want to route in a different way a client that is on `192.168.x.0` and a client that is on `192.168.y.0` network ? They are all in the same `192.168.x.x/16` network you have defined...(?) – krisFR May 30 '15 at 01:35

3 Answers3

17

You asked: "Can someone explain why this problem occurs in the first place?"

Based on what is reported in the official OpenVPN FAQ I bet it's caused by a routing problem within the OpenVPN engine.

To better clarify the scenario, let me refer to following diagram:

Here you can see:

  • an OpenVPN "server" connected to the HEADQUARTER internal network (10.0.1.0/24)
  • an OpenVPN "client" running at a Remote Site, and connected to the remote 192.168.1.0/24 network

Also

  • we're assuming that the OpenVPN tunnel is established and:
    • OpenVPN "server" is reachable via its own tun interface, with address 10.10.0.1. Also the P2P address, used by the tun interface is 10.10.0.2 (this is important for later discussion, so let's emphasize it)
    • OpenVPN "client" has a tun interface with IP 10.10.0.2

Now, let's assume that:

  • the OpenVPN "Client" has redefined it's default gateway, so to redirect within the tunnel all the outgoing IP traffic;
  • the OpenVPN "Client" has IP_FORWARDING enabled and, as such, can route packets coming from its internal LAN (192.168.1.0/24) (I'm emphasizing this point, as it's critical for our discussion).

With such a scenario in place, let's check in detail what happens when R_PC1 (192.168.1.2) send a packet, like an echo-request, to L_PC1 (10.0.1.2):

  1. after leaving R_PC1 NIC, the packet reach OpenVPN client;
  2. OpenVPN client (that is configured to act as a common router), route it according to it's routing table. As it's default-gateway is the tunnel, it sends the packet to the tunnel;
  3. Packet reach the tun interface of the OpenVPN server. OpenVPN will "see" it and, as it (OpenVPN server) knows that 10.0.1.2 is an address belonging to its LAN subnet, it "forward" the packet, from TUN to LAN;
  4. Packet reach L_PC1.

So everything is fine...

Now let's check what happens with the echo-reply that L_PC1 reply to R_PC1.

  1. echo-reply leaves L_PC1 NIC and reach OpenVPN server LAN interface (10.0.1.1);

Now, if we want OpenVPN Server being able to reach the remote site, we need to define the routing with a "static route". Something like:

route add -net 192.168.1.0 netmask 255.255.255.0 gw 10.10.0.2

Please note the P2P address used as gateway.

Such static routes will operate at OS-level. In other words, it's needed for the operating system to properly route the packet. It means something like: "Please, all the traffic addressed to 192.168.1.0/24 subnet needs to be forwarded to the OpenVPN engine, with whom the OS is able to talk via the P2P address". Thanks to such static route, now...

  1. the packet leaves the OS-routing context and reaches OpenVPN. The OpenVPN instance running on the OpenVPN Server. So, at this point, the OS has nothing more to do and all the routing (within the VPN) is left to the OpenVPN server software.

So, now, the problem is: how, the openvpn server software, will be able to decide the route of a packet, with SRC_IP 10.0.1.2 and DST_IP 192.168.1.2?

Please note that, based on the configuration of OpenVPN server, it knows nothing about the 192.168.1.0/24 network, nor the 192.168.1.2 host. It's not a connected client. It's not a local client. And so? OpenVPN, also, knows that it is not the "OS-Router", so it doesn't really want (and can....) send the packet back to the local gateway. So the only option, here, is to raise an error. Exactly the error you're experiencing

To say it with the language of the FAQ: "...it doesn't know how to route the packet to this machine, so it drops the packet...".

How can we solve the problem?

As you can see from the official documentation, the option iroute serves exactly to our scope:

--iroute network [netmask]
Generate an internal route to a specific client. The netmask 
parameter, if omitted, defaults to 255.255.255.255.
This directive can be used to route a fixed subnet from the server 
to a particular client, regardless of where the client is 
connecting from. Remember that you must also add the route to the 
system routing table as well (such as by using the --route 
directive). The reason why two routes are needed is that the 
--route directive routes the packet from the kernel to OpenVPN. 
Once in OpenVPN, the --iroute directive routes to the specific 
client.

So you need a:

--iroute 192.168.1.0 255.255.255.0

to be applied (to the server) when your OpenVPN client connect, for example via an ad-hoc configuration file defined on the server (client-config-dir, etc.).

Should you wonder why this problem does not happen at step 2) above, my understanding is that OpenVPN Client knows how to route it, 'cause it knows that the VPN-tunnel is a default-gateway.

The same cannot be done at OpenVPN Server, 'cause there the default gateway is tipically not overridden. Also, consider that you could have a single OpenVPN server with plenty of OpenVPN client: each client knows how to reach the server but... how can, the server, decide which is the client acting as a gateway for an unknown subnet?


As for your first question(Can the required rules be written in a generic/one-off way?), I'm sorry but I'm not getting your very problem. Can you rephrase providing more details?


Damiano Verzulli
  • 4,078
  • 1
  • 21
  • 33
  • 1
    Answering your last question: I don't want to edit the iroute configuration every time OpenVPN client connects from another public Wi-Fi just because it has different local network address. – jollyroger Jun 01 '15 at 08:05
  • 1
    @jollyroger : in tipical "road-warriors" scenario (a single PC acting as a vpn-client towards an openpn-server) you _DON'T_ need any "iroute" directive! So, if you connect via public-wifi, I'm sure you don't need it. You will need it only in tipical LAN-to-LAN configurations, where behind the OpenVPN client you have a whole network to be accessed by the OpenVPN server. I'm sure that this is _NOT_ the case when you connect... "from another public Wi-Fi". If my assumptions are wrong, please give details about your tipical network configuration (expecially when connecting via public-wifi) – Damiano Verzulli Jun 03 '15 at 20:14
  • This is mostly related to using SIP over OpenVPN. Assume you have 192.168.0.111/24 on your wlan0 and 10.10.10.5/30 on your tun0 connected to OpenVPN. Assume OpenVPN server has additional net 10.11.10.2/24 with Asterisk on 10.11.10.1 and all the needed routes are pushed to the client(ping succeeds in both directions). The problem is SIP can decide to route packets with source IP of your wlan0 to the tun0 interface instead of using tun0 source IP and this is when you get the issue — asterisk will think you are NAT-ed although you are not. – jollyroger Jun 04 '15 at 09:17
  • @jollyroger : if I'm right, it's perfectly possible to have SIP clients behind NAT boxes, so it should be possibile, within your OpenVPN client, to NAT outbound VPN traffic (leaving the tun0 interface). Are there some specific reasons why this is not an option, for you? – Damiano Verzulli Jun 04 '15 at 20:40
  • It works. but is not reliable (read my previous comment) due to the nature of SIP and buggy clients and the latter isn't changed for years. Sure, I can enable force proxying all traffic through my Asterisk server, but this limits clients to use only codecs supported by server despite having a possibility to route RTP packets directly with only client-to-client codec іnegotiation. – jollyroger Jul 16 '15 at 20:56
  • (Sorry for the archeology) Would a rule like ```iptables -t nat -A POSTROUTING -s $PRIVATE4 -o eth0 -j MASQUERADE``` help with the routing? What's the difference? Are both ```clinet-config-dir``` and ```MASQUERADE``` needed? – Nicolas C Aug 18 '17 at 15:36
1

I have experienced exactly the same problem, and also tried many recipes from discussion forums with push route and so on but the problem remained. The reason for this error was pretty simple: missing settings for iptables. Namely, on the server one should call something like

$ sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

where 10.8.0.0 is a virtual network created by OpenVPN-daemon and eth0 should be the name of the network interface on the server (see ifconfig output). Once this command is called everything works fine. But there was a catch: when I restarted the server, the iptables settings disappeared and the error

MULTI: bad source address from client [192.168.x.x], packet dropped

came back. So one has to call the iptables command above after each reboot. This can be solved as follows. First, save current iptables settings

$ sudo iptables-save > /etc/sysconfig/iptables

and then add the line

iptables-restore < /etc/sysconfig/iptables

to /etc/rc.d/rc.local so that these settings are loaded after each reboot.

P.S. And of course do not forget to uncomment/add the line

net.ipv4.ip_forward = 1

in /etc/sysctl.conf and apply changes by calling

$ sudo sysctl -p
John Smith
  • 301
  • 1
  • 5
1

I had a problem that seems similar, but I'm not sure if it's the same as your problem. I was trying to ping from an openvpn client to a computer in the openvpn server's local network (routed in the server's config), getting no reply and I could see the "bad source address" message in the server's openvpn log.

To solve it, I had to do 2 things:

  1. Enable ip forwarding on the server.
  2. Add a route for the vpn subnet on the server's gateway, because the gateway for the server's local network in my case is not the server itself, but a router. The pinged computer was trying to reply through the gateway, which had no idea what to do for the vpn subnet. So I added a static route in the router using the vpn subnet for the destination, and openvpn server's ip as the gateway for it.

That fixed it for me.

aditsu
  • 386
  • 1
  • 4
  • 10