https://bugzilla.novell.com/show_bug.cgi?id=700771 https://bugzilla.novell.com/show_bug.cgi?id=700771#c0 Summary: dhclient (dhcp) wipes out iptables connmark in firewall when renewing the lease Classification: openSUSE Product: openSUSE 11.4 Version: Final Platform: i586 OS/Version: openSUSE 11.4 Status: NEW Severity: Major Priority: P5 - None Component: Network AssignedTo: bnc-team-screening@forge.provo.novell.com ReportedBy: jimc@math.ucla.edu QAContact: qa@suse.de Found By: --- Blocker: --- User-Agent: Opera/9.80 (X11; Linux x86_64; U; en) Presto/2.8.131 Version/11.11 I upgraded my router to OpenSuSE 11.4 (kernel 2.6.37.6-0.5-desktop) with dhcp-client-4.2.1-0.7.1.i586 . I use a firewall depending on iptables connmarks: when the initial packet of the connection is acceptable a connmark bit is set (in the nat table for IPv4 and filter table for IPv6), and packets are tossed (in the filter table) if they lack this mark. Starting after the upgrade I found that no IPv4 TCP connection through the box could persist more than an hour, tested to several sites and ports. (IPv6 not tested.) Reproducible: Always Steps to Reproduce: 1. Get on a net where you get DHCP addresses (using dhclient). 2. Install an iptables rule that sets a connmark on a particular IP, port, etc. on the initial packet of a connection. Suggestion, use the SSH port (22). 3. Make a persistent connection that triggers the connmark. Look in /proc/net/nf_conntrack to make sure it's there. 4. Wait for the DHCP lease to be renewed. Actual Results: 5. Look in /proc/net/nf_conntrack -- the connmark is gone, and if (as in my case) it's part of your firewall, your connection is gone too. Expected Results: DHCP lease renewal should not wipe out the conntrack / connmark. I caught it in the act of killing a connection: I was playing streaming audio at the time. Jun 17 15:44:24 jacinth dhclient: DHCPREQUEST on eth1 to 71.104.222.1 port 67 Jun 17 15:44:24 jacinth dhclient: DHCPACK from 71.104.222.1 Jun 17 15:44:28 jacinth ifup: eth1 name: ASIX Electronics SMC2209USB/ETH Jun 17 15:44:31 jacinth dhclient: IP (71.104.222.28) unchanged, skip \ registration #(from my DynDNS registration hook) Jun 17 15:44:31 jacinth dhclient: bound to 71.104.222.28 -- renewal in \ 2845 seconds. And at this exact moment the stream stopped playing. The finger of blame points to the "ifup" step, which I didn't notice before the upgrade. I think dhclient does the DHCP negotiation and assigns the new IP address to the interface. Obviously since the IP has changed, all conntracks through that interface are useless and are tossed. Except the new IP address is identical to the old one. Dealing with details like this is not the job of iptables -- dhclient should be smart enough to leave the interface alone when the negotiated address is the same before and after. That logic is found in /sbin/dhclient-script (Copyright (C) 2010 SUSE...) Indeed, in the BOUND|RENEW|REBIND|REBOOT case, for IPv4 but not IPv6, only if the address has changed, it does "/sbin/ip addr add $new_ip_address..." (For IPv6, which is off topic, it does this unconditionally, see bug 690859.) Then it goes on to do "ifup $interface -o dhcp" unconditionally. I tried making that step conditional on an address change but the TCP connection was still killed. What I want the developers to do: help trace through the turgid logic of dhclient-script and /sbin/ifup, identify the command that is actually causing the conntracks to be cleared, and make it conditional on an actual change in the IP address. An analogous change for IPv6 is probably also needed. If I make any progress on this, I'll post the diff -- losing my connections once an hour really puts a crimp in my style when I'm trying to work from home. -- Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are on the CC list for the bug.