nginx stream的transparent

在nginx 1.11后面的版本中nginx stream proxy中增加了一个transparent。

具体使用如下

proxy_bind $remote_addr transparent;

官方的解释如下,有点看不懂。
The transparent parameter (1.11.0) allows outgoing connections to a proxied server originate from a non-local IP address, for example, from a real IP address of a client:

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.

那我们就测试一把, 建了一个dns的负载均衡。

stream {

log_format basic '$remote_addr [$time_local] '
                 '$protocol $status $bytes_sent $bytes_received '
                 '$session_time';


upstream dns {
  server 10.143.22.118:53;
  server 10.143.22.116:53;
}


server {
    listen 53 udp;
    access_log /data/nginx/log/udp53-access.log basic;
    proxy_responses 1;
    proxy_bind $remote_addr transparent;
    proxy_timeout 2s;
    proxy_connect_timeout 2s;
    proxy_pass dns;
}
}

我们从10.143.22.11 上使用dig来进行测试,一边我们在10.143.22.22上抓包。

 dig @10.143.22.22 -p 53 www.sssssss.com

结果抓包结果是:
10.143.22.22 有2次DNS请求。 一次是10.143.22.11对 10.143.22.22上进行的dns 查询。
另外一次居然是10.143.22.11针对10.143.22.118的查询。

这里问题就出现了,第二次完全没有经过10.143.22.22啊,那为什么在10.143.22.22的抓包数据里会有呢?

于是具体分析了一下2段数据包。

发现第二次请求是10.143.22.11的mac地址居然是10.143.22.22的mac地址的。原来是nginx直接把src的ip地址给改了。

而这样导致的结果是我上面那个dig查询没有返回,因为现在很多交换机上会把mac地址和IP地址进行了绑定,这样你这种伪造的IP地址就会被交换机给直接丢弃了。

为了验证这个说法,可以后面再使用tcp测试一下。