FPs

Haproxy 作爲Shadowsocks 中繼遇到的一個問題

之前用Haproxy 來轉發Shadowsocks 的流量時遇到一個問題,現象是在使用Slack 的時候(聊天使用了Websocket),頻繁重連。憑直覺是由於Haproxy 的某一項timeout 設置的不合理導致的。
Websocket 協議可以分爲2個階段,先用HTTP 握手,然後建立長連接,通過ws 協議進行通信。將Haproxy 作爲中繼時,在建立長連接之後,Haproxy 就轉入tunnel 模式

TUN:tunnel(option http-tunnel):这是 1.0 ~ 1.5-dev21 的默认模式,类似于隧道,HAProxy 仅处理第一个请求和响应,剩余的报文将直接转发而不进行处理。尽量不要使用这个模式,因为它在日志记录和 HTTP 处理上有很多问题。 --來源:liaoph.com

涉及到的timeout 見下圖:
timeout_websocket
圖片來源:www.yuangguo.info

我們遇到的需要頻繁重連的情況,其實是由於timeout tunnel 設置不合理導致的。官方給的關於timeout tunnel 的解釋:

Set the maximum inactivity time on the client and server side for tunnels.

The tunnel timeout applies when a bidirectional connection is established between a client and a server, and the connection remains inactive in both directions. This timeout supersedes both the client and server timeouts once the connection becomes a tunnel. In TCP, this timeout is used as soon as no analyser remains attached to either connection (eg: tcp content rules are accepted). In HTTP, this timeout is used when a connection is upgraded (eg: when switching to the WebSocket protocol, or forwarding a CONNECT request to a proxy), or after the first response when no keepalive/close option is specified......

另外官方給出了一個配置示例:

defaults http
    option http-server-close
    timeout connect 5s
    timeout client 30s
    timeout client-fin 30s
    timeout server 30s
    timeout tunnel  1h    # timeout to use with WebSocket and CONNECT

把中繼的Haproxy 的這項值設爲1h,解決了Slack 會頻繁重連的問題。

參考鏈接:

2016-07-27 haproxy websocket