I've just switched from an old Linux install (Debian squeeze) to a new one (Linux Mint 17.3) for my router (I am using a full desktop PC with a Linux install as my router). The Linux PC connects directly to my DSL modem and negotiates a PPPoE connection, then routes internet connections for all my other devices.

As far as I can tell, I've set it up the same as the previous Debian install. I had a simple rc.local script to set up iptables, and it's the same on the new box and it's getting run (I have ensured this by running /etc/rc.local from a root console). I've also setup DNS on the new box.

Most of the stuff works the same, but I am having one problem: the VPN on my Windows box no longer manages to connect. Looking at Wireshark, I notice that the initial PPTP packets seem to be successfully sent and received, but then there is a "Set-Link-Info" packet sent from my Windows box, and then the Windows box starts setting "PPP LCP Configuration Request" packets. At this point, it receives no response. The Wireshark capture going over my old Debian setup showed that at that point it got responses, eventually resulting in a "PPP LCP Configuration Ack".

I really can't figure out what else to check. I don't understand why the PPTP connection is getting stuck here with my new setup. Any ideas as to how I can troubleshoot?

Note: Here's the /etc/rc.local I have (it's the same on both installs) that sets up my entire iptables configuration:

#!/bin/sh -e

echo "*** Running rc.local ***"

# First up, make sure 'net.ipv4.ip_forward=1' exists, uncommented, in /etc/sysctl.conf (just do this manually)
echo "MAKE SURE net.ipv4.ip_forward=1 EXISTS, UNCOMMENTED, IN /etc/sysctl.conf OR NAT WILL NOT WORK!!!"
echo ""

# Firewall variables
#WAN_IFACE="eth0"         # At the time of writing, this is the NIC built into the mobo
WAN_IFACE="ppp0"         # Virtual PPP interface when using PPPoE
LAN_IFACE="eth1"         # At the time of writing, this is the extension NIC card
LAN_IP=""  # Class-C internal network

# Setup iptables... flush existing rules
iptables -F
iptables -t nat -F
set +e
# Set +e here to continue on error; iptables may give an error if this chain doesn't currently exist and we try to delete it
iptables -X LOGGING
set -e

# Set default policies for chains
iptables -P INPUT DROP

# Allow all local loopback access
iptables -A INPUT -i lo -p all -j ACCEPT
iptables -A OUTPUT -o lo -p all -j ACCEPT

# Allow incoming traffic for established connections
iptables -A INPUT -i $WAN_IFACE -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i $WAN_IFACE -p udp -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i $LAN_IFACE -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i $LAN_IFACE -p udp -m state --state RELATED,ESTABLISHED -j ACCEPT

# Allow incoming ICMP traffic
iptables -A INPUT -p icmp -j ACCEPT

# Uncomment lines in this section to allow unsolicited incoming traffic on ports
## Open common service ports
## SSH
#iptables -A INPUT -i $WAN_IFACE -p tcp --destination-port 22 -j ACCEPT
## HTTP (8080 + 8081)
#iptables -A INPUT -i $WAN_IFACE -p tcp --destination-port 8080 -j ACCEPT
#iptables -A INPUT -i $WAN_IFACE -p tcp --destination-port 8081 -j ACCEPT
iptables -A INPUT -i eth1 -p tcp --destination-port 8080 -j ACCEPT
iptables -A INPUT -i eth1 -p tcp --destination-port 8081 -j ACCEPT
iptables -A INPUT -i eth1 -p tcp --destination-port 53 -j ACCEPT
iptables -A INPUT -i eth1 -p udp --destination-port 53 -j ACCEPT
# Local Samba connections
iptables -A INPUT -p tcp --syn -s $LAN_IP --destination-port 139 -j ACCEPT
iptables -A INPUT -p tcp --syn -s $LAN_IP --destination-port 445 -j ACCEPT

# NAT setup - allow the NAT masquerading

# Allow forwarding of packets between the Internet and local network interface(s)

# Logging setup
iptables -N LOGGING
iptables -A LOGGING -m limit --limit 2/min -j LOG --log-prefix="IPTables-Dropped: " --log-level 4
iptables -A LOGGING -j DROP

# Logging; uncomment the below to log dropped input packets to syslog (verbose; only use for debugging!)
echo "Uncomment the necessary lines in rc.local to enable iptables logging..."
#iptables -A INPUT -j LOGGING

echo "*** Finished running rc.local ***"

exit 0


I've been doing some more investigation into this, and the Wireshark analysis of what's being put out by my Linux router reveals one very significant difference. Here are the two screenshots, first from my old Debian box whose routing works, and second from my new Mint box where it doesn't:

Wireshark on Debian squeeze

Wireshark on Linux Mint 17.3

I've replaced the IP addresses with red and blue stripes to indicate my Linux router's public IP address, and the remote address with which we are communicating in order to establish a VPN connection through the PPTP protocol. Also, my Windows machine's IP address on the local network is outlined in green.

The thing to notice is what happens after the PPTP protocol finishes and we switch to PPP LCP packets. On the Debian box, it continues to convert the source address of these packets to my public IP address before sending them out to the public internet. But on my Linux Mint box, the source address of packets being sent out is still kept as the local network address of my Windows machine that's trying to establish the connection. It's sending packets out to the internet with a local class C source address - of course they're not getting routed!

The question is, what is causing the breakdown of NAT here on my Linux Mint box that isn't happening on the Debian box? The iptables are the same, the /etc/network/interfaces are the same. I don't know... but maybe this discovery will help someone here to help me with the problem. :-)

  • The answers from derobert and Miroslav Banov together will get PPTP working, but please note that PPTP is thoroughly broken. At this point, you could just go ahead and not encrypt anything at all :) – Martin von Wittich Sep 6 at 11:24
up vote 3 down vote accepted

In order for NAT to work, you need to have a protocol-specific helper module loaded. By default, you're only going to have ones for TCP and UDP loaded.

That's why you're seeing your PPTP traffic (which is actually PPP over GRE) escaping without NAT. That module is nf_nat_proto_gre, at least as of Linux 4.4.

A similar story applies to connection tracking (without which GRE packets aren't going to be considered part of an established or related connection). That's nf_conntrack_proto_gre.

It turns out that PPTP requires special handling too (I'd guess it embeds IP addresses inside the PPP negotiation, but I haven't checked). That special handling is provided by nf_nat_pptp and tracking of PPTP connections is provided by nf_conntrack_pptp.

A modprobe ip_nat_pptp should get your VPN working. Dependencies between the modules will wind up loading all four. To make it continue working across boot, add nf_nat_pptp to /etc/modules.

(No, I have no idea where this is documented, sorry!)

  • Are ip_nat_pptp and nf_nat_pptp synonymous? Both seem to work interestingly. – Jez Apr 12 '16 at 17:57
  • @Jez yeah, they are ip_nat_pptp is an alias for nf_nat_pptp. I should probably use the non-alias in the answer for clarity, but they'll both work just fine. – derobert Apr 12 '16 at 18:01

The answer by derobert is correct. But with the newer kernel versions there is another problem - the default value of net.netfilter.nf_conntrack_helper is changed to 0 for security reasons.

See related:

The easy fix is to make it 1 again. Add at the bottom of /etc/sysctl.conf

net.netfilter.nf_conntrack_helper = 1

Then reboot.

Your Answer


By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.