使用HAProxy 1.6和一个聪明的黑客 ,我现在有一个HAProxy TCP模式前端,检测浏览器是否有能力的SNI,并在此基础上,路由到一个强encryption的SSLterminal后端,或者一个较弱的。 这确保了SSL实验室的A +分级,同时仍允许除IE6以外的所有浏览器使用SSL。
这是我的configuration。 它有一些模板variables应该是不言自明的,但不在与我的问题相关的领域:
frontend https_incoming bind 0.0.0.0:443 mode tcp option tcplog tcp-request inspect-delay 5s tcp-request content accept if { req.ssl_hello_type 1 } use_backend https_strong if { req.ssl_sni -m end .transloadit.com } default_backend https_weak backend https_strong mode tcp option tcplog server https_strong 127.0.0.1:1665 frontend https_strong bind 127.0.0.1:1665 ssl crt ${DM_ROOT_DIR}/envs/ssl/haproxy-dh2048.pem no-sslv3 no-tls-tickets ciphers ${strongCiphers} mode http option httplog option httpclose option forwardfor if-none except 127.0.0.1 http-response add-header Strict-Transport-Security max-age=31536000 reqadd X-Forwarded-Proto:\ https reqadd FRONT_END_HTTPS:\ on use_backend http_incoming backend https_weak mode tcp option tcplog server https_weak 127.0.0.1:1667 frontend https_weak bind 127.0.0.1:1667 ssl crt ${DM_ROOT_DIR}/envs/ssl/haproxy.pem no-sslv3 ciphers ${weakCiphers} mode http option httplog option httpclose option forwardfor if-none except 127.0.0.1 http-response add-header Strict-Transport-Security max-age=31536000 reqadd X-Forwarded-Proto:\ https reqadd FRONT_END_HTTPS:\ on use_backend http_incoming
问题: https_incoming前端知道客户端IP,但由于它处于mode tcp ,因此无法以mode http X-Forwarded-For标头mode http保存此信息。 option forwardfor在TCP模式下无效。
从serverfault上的另一个问题我已经发现我可以使用:
所以, X-Forwarded-For头不再需要了,因为据我所知,在LVS的情况下:数据包被欺骗,所以源变成客户IP,而在PROXY的情况下:数据包被封装以携带客户IP。
这两者似乎都可以工作。 然而,LVS对我们来说似乎是一种心脏手术,可能会有副作用,PROXY有代理/应用上游/下游的缺点,可能还不完全兼容。
我真的希望更轻量级的东西,那就是当我发现HAProxy 1.6的新“捕获”function时 :
您可以声明捕获槽,存储数据并在会话期间随时使用它。
它继续显示下面的例子:
defaults mode http frontend f_myapp bind :9001 declare capture request len 32 # id=0 to store Host header declare capture request len 64 # id=1 to store User-Agent header http-request capture req.hdr(Host) id 0 http-request capture req.hdr(User-Agent) id 1 default_backend b_myapp backend b_myapp http-response set-header Your-Host %[capture.req.hdr(0)] http-response set-header Your-User-Agent %[capture.req.hdr(1)] server s1 10.0.0.3:4444 check
在我看来,信息存储在一个前端,然后在后端使用,所以也许我可以采取在TCP模式下的客户端IP,保存它,并使用在线后,可能是这样的:
http-response set-header X-Forwarded-For %[capture.req.hdr(0)]
我已经看过捕获文档 ,看起来捕获更多地面向http模式头,但是我也看到了一个邮件列表会话 ,成功地演示了使用tcp-request capture 。
我已经尝试了几件事情,其中包括:
tcp-request capture req.hdr(RemoteAddr) id 0 # or tcp-request content capture req.hdr(RemoteHost) id 0
但是,正如你所看到的,我还不知道语法应该是什么,在哪些关键的信息将可用,我也不能在(我认为)有关的文件中find它。
问题:是否可以在TCP模式下捕获客户端IP,然后在线下将这些信息写入HTTP模式下的X-Forwarded-For头中? 如果是这样,这个语法是什么?
为了回答我自己的问题,这似乎不可能,因为这里的交通“离开”HAProxy:
TCP HTTP frontend->backend (->leaving->) frontend->backend
所以上下文丢失,捕获不能保存。 相反,昨天在Freenode的#haproxy的IRC上提出“PiBa-NL”
[5:29pm] PiBa-NL: kvz, use proxy-protocol between back and front [5:54pm] kvz: PiBa-NL: Thanks, does this mean my app also needs to understand the proxy protocol, or will it be 'stripped' once it reaches the backend. I don't think my node.js server could handle it without significant changes to its stack [6:07pm] kvz: Or let me rephrase: could I enable the proxy protocol on the first frontend, then 'unwrap' it in the second frontend, taking the client ip and putting it into the http header - so that my app would not have to be proxy protocol compatible, and it would just be means to carry the client ip from first frontend to the second? [6:49pm] PiBa-NL: kvz, the last part you can still use the x-forwarded-for header [6:50pm] PiBa-NL: but between haproxy backend and frontend you would use the proxyprotocol to make the second frontent 'know' the original client ip [6:50pm] PiBa-NL: server https_strong 127.0.0.1:1665 send-proxy [6:50pm] PiBa-NL: bind 127.0.0.1:1665 ssl crt .... accept-proxy [6:52pm] PiBa-NL: the second frontend can then still use the 'option forwardfor', and it should insert the wanted header [6:53pm] PiBa-NL: so basically 'yes'
这意味着PROXY协议仅用于将两个前端粘合在一起,封装Cient IP,但是第二个前端解包并通过option forwardfor将其保存在X-Forwarded-For头中,以便后端可以发送PROXY-无需协议的请求到我的应用程序服务器,这意味着我不必担心上/下游兼容性问题。
HAProxy应该已经添加了X-Forwarded-For头。 如果其中任何一个是非标准的,您可能需要添加协议和/或端口。
我通常testing这种行为与回应请求头的页面。 这可以很容易地看到什么标题可用,以及它们的内容是什么。
X-Forward-For包含地址列表并不罕见。 这表示请求已经通过多个代理,或者有人欺骗头。 最右边的地址将是处理请求的最后一个代理(ha-proxy)添加的地址。
某些Web服务器可以configuration为从一个标题而不是连接logging一个IP地址。 这对您的访问日志很有用,而且您可能希望根据传入的连接IP地址生成标题。
在支持除IE 6以外的所有列出的浏览器的情况下,可以实现A +评级而不使用两个不同的堆栈。
WinXP / IE8和Java 6不支持使用安全协议的前向保密,所以testing不会因为失败而受到惩罚。 如果您执行服务器sorting,所有其他浏览器将使用正向保密。 (如果你不这样做,手机会失败)
对A +的评级要求设置严格交通安全,时间至less为180天。