NGINX transparent TCP proxy


I have an ELK stack. In front of both Logstash hosts, I set up two NGINX loadbalancers as transparent proxies. UDP traffic is working as a charm. TCP works with the config:

stream {
  upstream syslog {
  server {
    listen 514;
    proxy_pass syslog;

But I get as source_ip and source_host the LB instead of the input server's IP.

Setting the same adding proxy_bind $remote_addr transparent; doesn't work, throwing a timeout.

*1 upstream timed out (110: Connection timed out) while connecting to upstream, client: $SOURCEHOST_IP, server:, upstream: "$LOGSTASH_IP:514", bytes from/to client:0/0, bytes from/to upstream:0/0

I tried setting up TPROXY from here:

Logstash host:

route add default gw $NGINX_IP
route del default gw $DEFAULT_GW

NGINX host:

# Following nginx how-to
iptables -t mangle -N DIVERT
iptables -t mangle -A PREROUTING -p udp -m socket -j DIVERT
iptables -t mangle -A DIVERT -j MARK --set-xmark 0x1/0xffffffff
iptables -t mangle -A DIVERT -j ACCEPT
iptables -t mangle -A PREROUTING -p tcp -s $LOGSTASH_IP/24 --sport 514 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 0
ip rule add fwmark 1 lookup 100
ip route add local dev lo table 100

# Enabling Upstream Servers to Reach External Servers
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE

But still failing like before with the Timeout.

What is missing to get a transparent TCP host?

asked on Stack Overflow Mar 31, 2017 by TanisDLJ

1 Answer


The official doc said: proxy_bind $remote_addr transparent;

In order for this parameter to work, it is usually necessary to run nginx worker processes with the superuser privileges. On Linux it is not required (1.13.8) as if the transparent parameter is specified, worker processes inherit the CAP_NET_RAW capability from the master process. It is also necessary to configure kernel routing table to intercept network traffic from the proxied server.


answered on Stack Overflow Jul 13, 2019 by Leon Jiang

User contributions licensed under CC BY-SA 3.0