LunaProxy - Top Proxy Service Provider with Over 200 Million IPs
VPN detection (P0f MTU)

Tutorials Detecting VPN (and its configuration!) and proxy users on the server side V3

No permission to download


Joined: Mar 15, 2021
Messages: 1,044
Resources: 405
Points: 113
Reaction score: 1,275
A lot of people use VPN every day. Somebody use it in always-on mode to circumvent government or corporative internet censorship, while somebody use it from time to time to bypass geographic restrictions. You may already know that huge video and music streaming services and game shops never really liked VPN users who easily bypass all restrictions to unblock country restricted content or to buy a game for less. Examples are plentiful: Netflix changed their ToS recently so that it can now terminate your account contract if you’re found to be circumventing its geo-restrictions, Hulu was also noticed for blocking VPN users, and Steam has been always suspicious to non-Russian speakers from Russia. Recently some companies tries to block not individual users but entire IP addresses of VPN services, which is troublesome for both users and VPN services. Seems like they don’t have any automatic tools and block addresses manually. While I’m against any type of censorship, I was curious if it is possible to detect VPN or proxy users on the server side.

And the answer is yes, under certain conditions. And pretty accurate.

MSS and MTU​

MTU or Maximum Transmission Unit stands for maximum data which could be transmitted in one packet. Every network adapter have its MTU value, even the routers between you and the remote side which transit your packets. Most of the time it is set to 1500, there are some exceptions though.

When you web browser or any other software working with the network creates TCP connection to the remote side, it adds Maximum Segment Size (MSS) value into TCP header, which informs remote size of the maximum TCP data size initiator can receive without packet fragmentation. This value is very similar to MTU.

As you try to open a web page with PPTP, L2TP(±IPsec) or IPsec IKE connected, your packet is encapsulated into another packet which introduces overhead. Large packets which could be sent without fragmentation without VPN connected now should be fragmented in order to be successfully delivered via your network, which lowers your speed and adds latency. In order to mitigate excessive fragmentation, OS sets lower MTU on the VPN interface then your real network interface MTU, preventing huge packets which would require fragmentation to be created. As far as I understand there is no standard or usual MTU sizes for PPTP, L2TP or IPsec. MTU value for said protocols is set by VPN administrators approximately, according to the minimum MTU size among all VPN users. OpenVPN, the most popular VPN solution, has chosen the other way.


To support old or just crappy software, OpenVPN doesn’t decrease interface MTU but decreases MSS inside encapsulated packet. That’s done with the mssfix setting which calculates OpenVPN overhead for the packet encapsulation and encryption and sets MSS accordingly for the packets to flow without any fragmentation. It is configured to work with any link with MTU 1450 or more by default. Because of this unique MSS values, we can determine not only if the user is connected via OpenVPN , but also used connection protocol (IPv4, IPv6), transport protocol (UDP, TCP), cipher, MAC and compression as they affect MSS.

Let’s take a look at a typical MSS values:

| Protocol | Block size | MAC | Compression | MSS |
| UDP | 64 | SHA1 | - | 1369 |
| UDP | 64 | SHA1 | + | 1368 |
| TCP | 64 | SHA1 | - | 1367 |
| TCP | 64 | SHA1 | + | 1366 |
| UDP | 128 | SHA1 | - | 1353 |
| UDP | 128 | SHA1 | + | 1352 |
| TCP | 128 | SHA1 | - | 1351 |
| TCP | 128 | SHA1 | + | 1350 |
| UDP | 128 | SHA256 | - | 1341 |
| UDP | 128 | SHA256 | + | 1340 |
| TCP | 128 | SHA256 | - | 1339 |
| TCP | 128 | SHA256 | + | 1338 |
If cipher uses 64 bit cipher then it’s probably Blowfish. If 128 — probably AES.

To prove my theory 2 VPN services has been tested: VyprVPN and ibVPN. Both of them could be identified using this method. If you don’t want to be identified, you can disable mssfix, just set it to zero on both server and client. With mssfix 0 your MSS would be 1460 which corresponds to MTU 1500 for IPv4 connection, and you’ll get fragmentation which leads to lower connection speed and higher latency. It may be better to disable OpenVPN mssfix and use more generic MSS values, like 1400 or 1380 (should be modulo 2 or better 10) as this values are often used for cellular connections. This could be set up using iptables on Linux.


There aren’t really much ways to detect proxy users if it doesn’t add any additional headers like X-Forwarded-For. But what drastically difference VPN from proxy? Remote VPN server receives packets your OS has created while proxy creates packets on its own and gets from you only data which should be transmitted. Different OS versions have their own unique fingerprints. Proxy is usually running under Linux or FreeBSD while web is browsed from Windows. Users are usually not aware that their OS version is transmitted in browser’s User-Agent header and don’t change it. That’s handy for us.


There is a great project called p0f which is very suitable for out needs. It can detect OS, MTU and browser passively and notify us about difference in OS and User-Agent fingerprints. It also has an API. A bit of modifying work and updating its signatures and voilà! we can detect popular VPN protocol users, proxy users and users who spoof their User-Agent header.
  • Tags
    detection mtu p0f vpn
  • Top