MENU

Haproxy使用TCP反代时获取真正的客户端IP

现在gitlab和アニメ已经迁入到了之前买的20o里,在迁入普通网站之前有一个问题,就是迁入之后网站如何获取到真实的客户端ip,虽然第一时间想到的是在软路由增加nginx,使用nginx进行反代,然而LEDE官方源的nginx并没有支持https,自己交叉编译nginx时也遇到了莫名其妙的错误,查阅各种资料的时候想起了Haproxy,网上翻阅了不少Haproxy的透明代理资料,外加各种实践,然后总结出了这篇文章.

环境

软路由使用的系统是LEDE,主要负责小鸡的NAT,小鸡从LEDE获取内网IP
小鸡使用现成的宝塔面板
软路由安装Haproxy

软路由上的Haproxy配置

opkg update
opkg install haproxy

安装好Haproxy后配置文件在/etc/haproxy.cfg,我们打开这个文件,里面各种说明还有3个示例,经过修改和精简最后得到以下内容,这就是直接可以用的配置文件

global
    maxconn 32000
    ulimit-n 65535
    uid 0
    gid 0
    daemon
    nosplice

listen website_80
    bind 外网ip:80
    mode tcp
    server website 内网小鸡ip:80 check send-proxy
    
listen website_443
    bind 外网ip:443
    mode tcp
    server website 内网小鸡ip:443 check send-proxy

将此文件保存之后使用/etc/init.d/haproxy start启动Haproxy即可

小鸡里的Nginx配置

注意,小鸡里的nginx必须配置,不配置直接访问会出现400错误,因为Haproxy修改了数据包.
首先编辑主配置文件/www/server/nginx/conf/nginx.conf在http层内加入一行log定义,内容如下

log_format elb_log '$proxy_protocol_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent "$http_referer" ' '"$http_user_agent"';

然后编辑你的网站配置文件,加入proxy_protocolreal_ip_header等、示例代码如下

listen 80 proxy_protocol; 
listen 443 ssl http2 proxy_protocol;
set_real_ip_from x.x.x.x; #这里的ip是软路由的内网IP也就是你的小鸡的网关
real_ip_header proxy_protocol;

然后重载你的nginx即可正常访问你的网站,并且可以正常获取到真实的客户端IP

LEDE端口冲突解决

LEDE的web界面占用了80端口,会导致Haproxy不能绑定外网端口,解决方法也很简单,编辑/etc/config/uhttpd,将里面listen_httplisten_https的端口号修改一下即可,注意去掉注释,这个文件好像不支持注释

config uhttpd 'main'
    list listen_http '0.0.0.0:80' #修改这里的端口号
    list listen_http '[::]:80' #修改这里的端口号
    list listen_https '0.0.0.0:443' #修改这里的端口号
    list listen_https '[::]:443' #修改这里的端口号
    option redirect_https '1'
    option home '/www'
    option rfc1918_filter '1'
    option max_requests '3'
    option max_connections '100'
    option cert '/etc/uhttpd.crt'
    option key '/etc/uhttpd.key'
    option cgi_prefix '/cgi-bin'
    option script_timeout '60'
    option network_timeout '30'
    option http_keepalive '20'
    option tcp_keepalive '1'
    option ubus_prefix '/ubus'

然后执行下面两句

/etc/init.d/uhttpd restart
/etc/init.d/haproxy restart

然后就没有然后了

添加新评论

已有 7 条评论
  1. 免费ssl不能自动刷新每日限额了@(泪)

  2. 可以的,虽然我暂时用不上@(滑稽)

  3. nginx性能太低,不好使,Haproxy还行,但是我更加喜欢kangle,@(哈哈)

  4. 博主可以试下国人做的一款叫frp的反向代理,go语言写的,性能还不错
    Github地址:https://github.com/fatedier/frp

    1. @KasuganoSoragolang的程序并不能在lede上跑,而且我的目的是在不修改php文件的情况下获取真正的客户端ip

  5. 我用的是另一种方案,无需配置被反代的webserver,只在蛤代理上配置就好了,基本思路是由蛤代理自己来完成上面nginx的配置完成的事情,需要在蛤代理的frontend与backend之间再各加一层frontend与backend。

    1. @南浦月有没有相关链接,我去看看