wangbin
  • wangbin
  • 2018-04-25
  • IT

4层代理haproxy

一. 简介

最近发现了haproxy,工作在7层协议第4层,感觉非常牛逼!!!

之前一直用的nginx,是工作在7层,虽然现在也可以进行4层代理了,但是可配置的参数太少,远不如haproxy操作空间那么大。

二. 安装

install_haproxy.sh

wget http://www.haproxy.org/download/1.8/src/haproxy-1.8.3.tar.gz
tar zxvf haproxy-1.8.3.tar.gz 
cd haproxy-1.8.3
make TARGET=linux415 ARCH=x86_64 PREFIX=/usr/local/haproxy USE_LINUX_TPROXY=1
make install PREFIX=/usr/local/haproxy 

// 创建conf配置文件夹
mkdir -p /usr/local/haproxy/conf

其中TARGET=linux415,415标识内核版本,可以使用uname -r查看,如:4.15.14-1.el7.elrepo.x86_64,此时该参数就为linux415

如果返回结果是2.6.28,可以用:TARGET=linux2628

三. 配置

/usr/local/haproxy/conf/haproxy.cfg

global
log /dev/log    local0
log /dev/log    local1 notice
chroot          /var/lib/haproxy
pidfile         /var/run/haproxy.pid 
daemon

defaults
    log global
    mode    tcp
    option  tcplog  
    option  dontlognull
    maxconn 2000
    timeout connect  5000
    timeout client 500000
    timeout server 500000

frontend ssl
    mode tcp
    bind 0.0.0.0:443
    tcp-request inspect-delay 3s
    tcp-request content accept if { req.ssl_hello_type 1 }

    acl tls req.ssl_hello_type 1

    acl has_sni req.ssl_sni -m found

    use_backend nginx if tls has_sni

    acl ssh_payload payload(0,7) -m bin 5353482d322e30
    use_backend openssh if ssh_payload
    use_backend openssh if !{ req.ssl_hello_type 1 } { req.len 0 }

backend nginx
    mode tcp
    server webserver 127.0.0.1:50443

backend openssh
    mode tcp
    timeout server 3h
    server openssh 127.0.0.1:50022

其中

frontend ssl
    mode tcp
    bind 0.0.0.0:443

监听本地443端口tcp协议

backend nginx
backend openssh

后端有nginx和openssh, nginx工作在本地50443端口tcp协议上,openssh工作在本地50022端口tcp协议上。

那是怎么判断请求是该转发nginx还是openssh的呢?

后端nginx

acl tls req.ssl_hello_type 1

根据请求中ssl_hello_type,判断请求是否是tls

acl has_sni req.ssl_sni -m found

根据请求中ssl_sni,判断请求是否有SNI扩展,SNI(Server Name Indication)是为了解决一个服务器使用多个域名和证书的SSL/TLS扩展。

use_backend nginx if tls has_sni

如果请求同时是tls,且有sni扩展,那么转发后端nginx。

后端openssh

acl ssh_payload payload(0,7) -m bin 5353482d322e30

利用payload来进行判断是否是ssh

use_backend openssh if ssh_payload
use_backend openssh if !{ req.ssl_hello_type 1 } { req.len 0 }

openssh请求的len不会是0

其他判断参数

acl is_http req.payload(0,3) -m bin 474554 504f53 505554 44454c
acl is_ssh req.payload(0,3) -m bin 535348    
acl is_rdp req.payload(0,3) -m bin 030000    

四. 命令

启动

/usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.cfg

五. 结尾

这种转发nginx有个弊端,就是nginx的所有日志获取的ip都是127.0.0.1了,不过可以解决,就是用上面编译带上的tproxy做透明代理,但是很麻烦的样子,目前我还没弄好。

不过4层代理haproxy,还是很牛逼的!!!

参考:

  1. https://siukwan.sinaapp.com/?p=960