I've been trying to track down this problem for several days. I still haven't worked out what is going on, or how to fix it properly, but I do have a workaround.
Problem summary
Netflix stalls when watching on any machine on my internal network, accessing the internet via a linux box acting as nat router and adsl. Netflix works fine when watching directly on the linux box connected to the internet.
Details
My linux server box, "chimp", is connected to the house internal network via one nic (eth0) and to the adsl modem via another nic (eth3). It is running pppoe to the adsl modem, and the internet link works fine, with 15Mb/s down and 1Mb/s up. Chimp is running debian jessie 8.6.0 (kernel 3.16.0-4-amd64), although it was debian wheezy 7.1.0 until I upgraded it as part of investigating this problem.
Other computers on the house network access the internet via iptables rules on chimp that use masquerading (I also tried snat) to forward from eth0 to ppp0.
Watching netflix on chimp itself works fine. Watching BBC iplayer (I'm in the UK) on any computer on the network works fine. Watching netflix on any computer other than chimp stalls, although I believe it used to work around about the start of November 2016. Computers showing the problem include a couple of macs (safari) plus another debian jessie box (chrome).
Looking at the "RX bytes" figure from "/sbin/ifconfig ppp0" showed it was downloading for a few seconds, then pretty much stopped.
I found something on the internet that said that my iptables rules should be dropping packets that conntrack marks as "invalid". I added rules to drop invalid packets, but it did not improve the situation. I tried logging as well, and I saw that I was getting a bunch of such packets back from netflix, but only when watching on a machine other than chimp.
I tried "echo 255 >/proc/sys/net/netfilter/nf_conntrack_log_invalid" and saw that the invalid packets were due to bad TCP checksums:
Dec 30 20:16:40 chimp kernel: [185803.594182] nf_ct_tcp: bad TCP checksum IN= OUT= SRC=78.146.119.61 DST=<my_public_ip_address> LEN=1500 TOS=0x00 PREC=0x00 TTL=59 ID=0 PROTO=TCP SPT=443 DPT=56711 SEQ=92431783 ACK=3940029300 WINDOW=2050 RES=0x00 ACK URGP=0 OPT (0101080AC67B959B27E48AC7)
Dec 30 20:16:40 chimp kernel: [185803.594200] input invalid: IN=ppp0 OUT= MAC= SRC=78.146.119.61 DST=<my_public_ip_address> LEN=1500 TOS=0x00 PREC=0x00 TTL=59 ID=0 PROTO=TCP SPT=443 DPT=56711 WINDOW=2050 RES=0x00 ACK URGP=0
(The "input invalid" prefix shows that it comes from my iptables rule to log an invalid packet in the input chain just before dropping it.)
I tried disabling checksum checking in conntrack with "sysctl -w net.netfilter.nf_conntrack_checksum=0". That made the above log lines stop, but didn't fix the problem.
So my best guess is:
- Something is broken upstream from me sending me a netflix stream, so I get TCP checksum errors.
- When watching netflix on chimp, an erroneous packet arrives in chimp's tcp layer and it is able to recover, perhaps by asking for the packet again.
- When watching on another machine, even with tcp checksum checking disabled, conntrack fails to associate the packet with the connection so it never arrives at the client machine's tcp layer. The client's tcp layer recovers in a more drastic way, perhaps with a longer timeout or by erroring the whole connection.
Actual question at last
Does that make any sense to anyone who knows more about tcp, conntrack and nat than I do? Or is there something I could be doing wrong?
Workaround
I've kind of run out of steam investigating this. But maybe this workaround will be useful for anyone else encountering the same problem.
The workaround is to set the whole house network using an http/https proxy running on chimp (the machine connected to the internet). I used wpad.dat on chimp to autoconfigure the other machines, and set it up to only proxy *.netflix.com and *.nflxvideo.net.
Each client machine needs a bit of configuration to use proxy auto-discovery, just a single check box in network settings on both mac and gnome (and I guess the same on windows).
Output from iptables -L -xvn
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 state INVALID LOG flags 0 level 4 prefix "input invalid: "
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 state INVALID
347 19177 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
259 33840 ACCEPT all -- eth+ * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpts:1024:5999
0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpts:6010:65535
0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:123
0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:500
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:25
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:143
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:993
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8443
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp flags:!0x17/0x02
0 0 ACCEPT 47 -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT esp -- * * 0.0.0.0/0 0.0.0.0/0
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
0 0 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 state INVALID LOG flags 0 level 4 prefix "forward invalid: "
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 state INVALID
0 0 ACCEPT tcp -- eth0 ppp+ 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp flags:!0x17/0x02
0 0 ACCEPT udp -- eth0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
0 0 ACCEPT udp -- * eth0 0.0.0.0/0 0.0.0.0/0 udp spt:53
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 639 packets, 103120 bytes)
pkts bytes target prot opt in out source destination
Output from iptables-save
# Generated by iptables-save v1.4.21 on Mon Jan 2 13:24:22 2017
*nat
:PREROUTING ACCEPT [115:43215]
:INPUT ACCEPT [43:4146]
:OUTPUT ACCEPT [2:606]
:POSTROUTING ACCEPT [2:606]
-A POSTROUTING -o ppp+ -j MASQUERADE
COMMIT
# Completed on Mon Jan 2 13:24:22 2017
# Generated by iptables-save v1.4.21 on Mon Jan 2 13:24:22 2017
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [692:108312]
-A INPUT -m state --state INVALID -j LOG --log-prefix "input invalid: "
-A INPUT -m state --state INVALID -j DROP
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth+ -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -p udp -m udp --dport 1024:5999 -j ACCEPT
-A INPUT -p udp -m udp --dport 6010:65535 -j ACCEPT
-A INPUT -p udp -m udp --dport 123 -j ACCEPT
-A INPUT -p udp -m udp --dport 500 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 143 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 993 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 8443 -j ACCEPT
-A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -j ACCEPT
-A INPUT -p gre -j ACCEPT
-A INPUT -p esp -j ACCEPT
-A INPUT -j DROP
-A FORWARD -i lo -j ACCEPT
-A FORWARD -m state --state INVALID -j LOG --log-prefix "forward invalid: "
-A FORWARD -m state --state INVALID -j DROP
-A FORWARD -i eth0 -o ppp+ -p tcp -j ACCEPT
-A FORWARD -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -j ACCEPT
-A FORWARD -i eth0 -p udp -m udp --dport 53 -j ACCEPT
-A FORWARD -o eth0 -p udp -m udp --sport 53 -j ACCEPT
-A FORWARD -j DROP
COMMIT
# Completed on Mon Jan 2 13:24:22 2017