公司有业务场景,利用了haproxy功能,后端服务需要记录应用端的来源,以便审计等用处。
haproxy分为4层与7层,我们的业务场景是使用4层tcp协议。
经过一番折腾,终于搞定了,下面记录下。
1.haproxy配置
下面是harpoxy的相关配置,重点是后端服务处的check send-proxy 选项,才实现了ip透传功能。
global
daemon
nbproc 2
user root
group root
maxconn 60000
tune.maxaccept -1
spread-checks 5
stats bind-process 1
stats socket 127.0.0.1:13 mode 0666 level admin
defaults
log global
option dontlognull
option forwardfor
option accept-invalid-http-response
mode http
retries 3
option redispatch
timeout connect 5s
timeout client 0s
timeout server 0s
timeout http-keep-alive 100s
option http-keep-alive
option http-server-close
listen status
mode http
bind *:14
bind-process 1
stats enable
stats hide-version
stats uri /deimos?stats
stats realm Deimos\ Stats
stats auth deimos:deimosgogogo
stats refresh 5s
stats admin if TRUE
frontend f_1208ee9c687d834bba12e600e03d3f60
maxconn 60000
bind 2.2.2.2:3306
mode tcp
default_backend 1208ee9c687d834bba12e600e03d3f60
backend 1208ee9c687d834bba12e600e03d3f60
mode tcp
balance roundrobin
timeout check 2s
server server0 1.1.1.1:3306 weight 1 check inter 2s fall 3 check send-proxy
server server1 1.1.1.2:3306 weight 1 check inter 2s fall 3 check send-proxy
server server2 1.1.1.3:3306 weight 1 check inter 2s fall 3 check send-proxy
2.客户端语言获取IP方法
由于我们用的是go客户端,下面是获取前端真实IP的方法,有现成的包可以使用,github.com/pires/go-proxyproto,其他语言应该也有类似的方法。
header,_ := c.ReadHeaderfromHaproxyProto()if header != nil {
c.ClientHost = fmt.Sprintf("%s:%v",header.SourceAddress.String(),fmt.Sprint(header.SourcePort))
}
proto "github.com/pires/go-proxyproto")// ReadHeaderfromHaproxyProto read header package from HaproxyProto func(c *Conn)ReadHeaderfromHaproxyProto()(*proto.Header,error){ return proto.Read(c.bufferedReader)