最近发现同时在443上监听tcp和http协议会有ssl握手的问题,具体表现就是需要握手失败3次才能正确的sni转发。
前情提要
之前写过一篇利用haproxy复用443端口同时使用tcp和http协议,在配置中实现了tcp和http协议利用sni分流同时监听在443的端口,但是这样会造成一定的问题,就是谁先谁后的问题,经常需要握手几次失败之后才能正确的识别到。
故重新配置了一下配置文件,实现了全部由tcp443进站,然后利用sni分流给后端,利用tcp或者sock文件转成http协议。
配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
| global log /dev/log local0 log /dev/log local1 notice user haproxy group haproxy unix-bind user haproxy unix-bind group haproxy unix-bind mode 660 chroot /var/lib/haproxy stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners stats timeout 30s daemon
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384 ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
defaults log global mode tcp option tcplog option dontlognull timeout connect 24h timeout client 24h timeout server 24h
frontend http_in mode http bind *:80 http-request redirect scheme https
frontend https_in mode http bind 127.0.0.1:9443 ssl crt /usr/local/etc/haproxy/cert alpn h2,http/1.1 accept-proxy
option httplog log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r" capture request header Host len 40 capture request header User-Agent len 100 capture request header X-Forwarded-For len 15
acl host_blog hdr(host) -i xx.xx.xx acl host_webdav hdr(host) -i xx.xx.xx acl host_s3 hdr(host) -i xx.xx.xx use_backend webdav_backend if host_webdav use_backend s3_backend if host_s3 use_backend blog_backend if host_blog default_backend default_backend
frontend tcp_in mode tcp bind *:443
tcp-request inspect-delay 5s tcp-request content accept if { req.ssl_hello_type 1 } acl host_app req_ssl_sni -m sub zxxx acl host_trojan req_ssl_sni -i xxx acl host_vless req_ssl_sni -i xxxx use_backend forward_backend if host_app use_backend trojan_backend if host_trojan use_backend vless_backend if host_vless default_backend tcp_to_https
backend tcp_to_https mode tcp server local-https 127.0.0.1:9443 send-proxy-v2 timeout connect 5s timeout server 30s
backend webdav_backend mode http server filen_webdav 127.0.0.1:8190 check
backend s3_backend mode http server filen_s3 127.0.0.1:8191 check
backend blog_backend mode http option forwardfor option http-server-close http-request set-header X-Forwarded-For %[src] http-request set-header X-Real-IP %[src] http-request set-header Host xxxx server nginx_server xxxxxx ssl check verify none check-sni blog.zdawn.net sni str(blog.zdawn.net) inter 2000 rise 2 fall 4
backend forward_backend mode tcp option ssl-hello-chk server blog_server 2xxxxx weight 1 check inter 2000 rise 2 fall 4
backend trojan_backend mode tcp server trojan_server 127.0.0.1:9000 check
backend vless_backend mode tcp server vless_server 127.0.0.1:9010 check
backend default_backend mode http http-request den
|
后记
利用sock的方式我一直有权限的问题,故更换了tcp的方式,这种方式更加的稳定一些。
现在就可以愉快的玩耍了。