There seems to be some weird interaction between haproxy tcp mode and ipfw's NAT which cause connections to be killed prematurely and I'm hoping someone can help me troubleshoot this.
On this VPS I have 2 jails, one running nginx (172.16.0.6) and one running haproxy (172.16.0.4). These addresses are on the lo1 interface. On the nginx server I have a 32k test file I'm trying to download.
The haproxy config is very basic:
This works just fine. I can curl http://172.16.0.4/32k.file and get the full file with no problem.
The ipfw config to nat inbound 80 and redirect to haproxy is also very simple:
But for some reason this doesn't work. When I curl http://outside-ip/32k.file curl reports the connection closed with 16640 bytes remaining to read.
If I take haproxy out of the picture, and redirect to $nginx:80 instead, everything works fine.
Also everything works fine if I use pf instead of IPFW. This is the pf config that works.
Here's what I get from curling the outside address with PF, where everything works fine:
But here's what I get with ipfw active where the connection is closed early:
On this VPS I have 2 jails, one running nginx (172.16.0.6) and one running haproxy (172.16.0.4). These addresses are on the lo1 interface. On the nginx server I have a 32k test file I'm trying to download.
The haproxy config is very basic:
Code:
frontend fe
bind 0:80
mode tcp
default_backend be
backend be
mode tcp
server be01 172.16.0.6:80
The ipfw config to nat inbound 80 and redirect to haproxy is also very simple:
Code:
#!/bin/sh
# Flush out the list before we begin.
ipfw -q -f flush
cmd="ipfw -q add"
ext_if="vtnet0"
haproxy="172.16.0.4"
nginx="172.16.0.6"
ipfw -q nat 1 config if $ext_if \
redirect_port tcp $haproxy:80 80
$cmd 0100 nat 1 ip4 from any to any via $ext_if
$cmd 00610 allow ip from any to any
If I take haproxy out of the picture, and redirect to $nginx:80 instead, everything works fine.
Also everything works fine if I use pf instead of IPFW. This is the pf config that works.
Code:
ext_if = vtnet0
haproxy = 172.16.0.6
nginx = 172.16.0.5
nat on $ext_if from any to any -> ($ext_if)
rdr on $ext_if proto tcp from any to any port 80 -> $haproxy port 80
pass in all
Here's what I get from curling the outside address with PF, where everything works fine:
Code:
$ curl -v http://X.X.X.X/32k.file > /dev/null
* Trying X.X.X.X...
* TCP_NODELAY set
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to X.X.X.X (X.X.X.X) port 80 (#0)
> GET /32k.file HTTP/1.1
> Host: X.X.X.X
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.12.0
< Date: Sat, 29 Apr 2017 14:47:30 GMT
< Content-Type: application/octet-stream
< Content-Length: 32768
< Last-Modified: Sat, 29 Apr 2017 14:42:19 GMT
< Connection: keep-alive
< ETag: "5904a64b-8000"
< Accept-Ranges: bytes
<
{ [14224 bytes data]
100 32768 100 32768 0 0 231k 0 --:--:-- --:--:-- --:--:-- 233k
* Connection #0 to host X.X.X.X left intact
But here's what I get with ipfw active where the connection is closed early:
Code:
$ curl -v http://X.X.X.X/32k.file > /dev/null
* Trying X.X.X.X...
* TCP_NODELAY set
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to X.X.X.X (X.X.X.X) port 80 (#0)
> GET /32k.file HTTP/1.1
> Host: X.X.X.X
> User-Agent: curl/7.54.0
> Accept: */*
>
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0< HTTP/1.1 200 OK
< Server: nginx/1.12.0
< Date: Sat, 29 Apr 2017 14:50:27 GMT
< Content-Type: application/octet-stream
< Content-Length: 32768
< Last-Modified: Sat, 29 Apr 2017 14:42:19 GMT
< Connection: keep-alive
< ETag: "5904a64b-8000"
< Accept-Ranges: bytes
<
{ [1192 bytes data]
30 32768 30 9880 0 0 8694 0 0:00:03 0:00:01 0:00:02 8689* transfer closed with 16640 bytes remaining to read
49 32768 49 16128 0 0 13085 0 0:00:02 0:00:01 0:00:01 13080
* Closing connection 0
curl: (18) transfer closed with 16640 bytes remaining to read