9

I have successfully set up an OpenVPN server on Debian (raspberry pi model b+). With the protocol set to TCP it works exactly as desired (internet routed through VPN, access to local network machines), however when I set the protocol to UDP (which I think would be desirable for better speed) then I find I am able to ping any host (IP address or domain name), I can telnet and ssh (again ip address or domain) but when I try to open a page in a browser it appears to make an initial connection but then never loads.

Do you have any ideas why web browsing would be a problem for the UDP mode?

I've set up UFW to manage iptables, the main configuration line for this was added to before.rules

*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# Allow traffic from OpenVPN client to eth0
-A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
COMMIT

Since everything works properly for TCP and very nearly properly for UDP then I think the problem is not down to firewall/iptables but I could be wrong.

My openvpn server configuration is

local 192.168.0.31
dev tun
proto tcp
port 1194
ca ca.crt
cert server.crt
key server.key
dh dh1024.pem
server 10.8.0.0 255.255.255.0
ifconfig 10.8.0.1 10.8.0.2
push "route 10.8.0.31 255.255.255.255"
push "route 10.8.0.0 255.255.255.0"
push "route 192.168.0.31 255.255.255.0"
push "dhcp-option DNS 192.168.0.1"
push "redirect-gateway def1"
push "explicit-exit-notify 3"
client-to-client
duplicate-cn
keepalive 10 120
tls-auth ta.key 0
cipher AES-128-CBC
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn-status.log 20
log /var/log/openvpn.log
verb 1

Does anyone have any ideas why there may be a problem?

2
  • 2
    This sounds like an MTU problem. Reduce the MTU on your VPN to something "safe" like 1000 and see if that changes anything.
    – qasdfdsaq
    Aug 12, 2015 at 10:10
  • That did it! Thanks very much. I've never come across MTU before so it's good to learn something new. Could you form it into an answer with maybe a bit of an explanation as to what was going on? Aug 12, 2015 at 15:01

1 Answer 1

16

These particular symptoms (with a VPN) are fairly common symptoms indicating an issue with your path MTU.

MTU basics

The path MTU (Maximum transmission unit) is the largest packet that can traverse between two devices on the internet (or any other network). Each link along the path has its own MTU, which may or may not match the others. The overall path MTU is the lowest MTU along the entire path.

If your computer attempts to send a packet larger than than the path MTU, the data packet is dropped at the hop which it exceeds, and the data will never arrive. In well-behaved networks, your computer should receive an error response and know to auto-adjust the MTU down and/or fragment subsequent packets. On badly-behaved networks, it might just be dropped silently.

Path MTU (auto)discovery is the mechanism used to automatically detect the MTU between you and the VPN server, however it is more robust with TCP than with UDP on badly-behaved networks, because TCP mandates explicit feedback that can tell you which packets don't arrive.


The reason it acts the way it does with VPN links is because the VPN encapsulation headers reduce the MTU of your tunnelled connection, and because UDP provides no feedback on dropped packets.

If your real PMTU is, for example, 1400 bytes, sending a 1400-byte packet through a VPN might take 1432 bytes. Over a TCP connection, if you try to send a 1432 byte packet, TCP can tell it doesn't arrive and fragments it and sends it again as a 1400 byte packet and a second 32 byte packet (that's a gross simplification nonetheless). With UDP it just gets dropped silently. However, in both cases, sending any packet smaller than 1400 bytes will succeed.

This is why SSH and telnet works whereas web browsing doesn't. Your VPN has reduced your MTU below your default, but your OS hasn't realized either because error messages are not being returned properly or PMTU autodiscovery isn't working. But because SSH and telnet and ping all use very small packets (typically <100 bytes), if your MTU has been reduced from 1400 to 1368 (1400 - 32), it doesn't matter, as they are still much smaller than the limit. SSH and telnet typically send between one byte and one line at a time, plus packet headers. Ping packets are typically up to 64-bytes plus packet headers, again much smaller than any sane MTU (1400+)

Web browsing initially connects because the DNS, TCP SYN/ACK packets and HTTP requests are both usually much smaller than 1400 bytes, but as soon as the website tries to send the actual web page, it'll use full-size packets which then get silently discarded along the way.


Solving the problem

There's the easy (cheaty) way, and the other way which involves figuring out what the problem actually is.

The cheaty way being to set the MTU much lower manually - for example to 1000, so everything will fit inside even the reduced MTU of the VPN. This in itself is a good test to see if the MTU is the problem.

The better way would be to figure out where the problem lies, and fix it. MTU autodiscovery problems can arise because of a crappy server or ISP, which you can do nothing about, or local firewall/configuration issues, which you can fix. It may be your OpenVPN routing and firewall rules aren't allowing ICMP error messages to get back to your machine.

An intermediate method would be to figure out the true maximum MTU and set that manually - you can start with something small like 1000 bytes and work upwards to find the highest value that works. Basically, connect your VPN using UDP, and then ping something through the VPN with the command ping -f <server address> -l <packet size> and increase packet size upwards until it stops working - either with a timeout or an error.

1
  • Did you mean -s instead of -l? In my ping from iputils s20190709, -l is for preload.
    – slhck
    May 28, 2021 at 7:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .