I am trying to setup a captive web portal redirect on CentOS using the following configuration:
This configuration works for the first few packets, but then suddenly the destination port is corrupted in the response from the server. The packet trace looks like this:
Client: The host making the original web request. Server: Original destination for the request Portal: Captive portal server
This packet trace is taken from a place that can see both the client and portal traffic. Lines that start with c: are from the client side, and p: are from the portal side.
c: client:57877 -> server:80 [SYN] p: client:1092 -> portal:80 [SYN] NAT adjusted SYN p: portal:80 -> client:1092 [SYN, ACK] c: server:80 -> client:57877 [SYN, ACL] NAT reversed on the SYN/ACK c: client:57877 -> server:80 [ACK] c: client:57877 -> server:80 HTTP GET p: client:1092 -> portal:80 [ACK] p: client:1092 -> portal:80 HTTP GET p: portal:80 -> client:1092 [ACK] c: server:68 -> client:57877 [ACK] ^^ WTF?!?
At this point the connection is hosed. The client isn't expecting a packet on that port and sends a RST. The broken port number increments by 1 every time this connection is attempted (presumably it will work once 12 attempts from now). All retransmissions have the same broken port number on the response. I have no idea what could be causing this.
Is this a bug, or am I doing something wrong? This machine does have a somewhat unusual configuration. It is configured as a bridge. In order to only apply the NAT rule to packets going in a single direction, the packets are marked with an ebtables NAT rule first, and that mark is checked when the iptables NAT is applied.
This is on Enterprise Linux 6 with Kernel 2.6.32-279.5.2.el6.x86_64
The NAT rule is:
target prot opt in out source destination DNAT tcp -- ilb any anywhere anywhere multiport dports http,https mark match 0x8 to:<portal IP>
ilb is the bridge.