menu Chancel's blog
rss_feed
Chancel's blog
我就是这样的人

解决不同代理协议负载均衡设置之Privoxy+Haproxy

作者:Chancel, 更新:2019 Dec 05, 字数:3939, 已阅:1006

这篇文章更新于 1270 天前,文中部分信息可能失效,请自行甄别无效内容。

有时候我们的公司内网网络需要代理才能访问外网网页,公司也会提供多个代理来让我们访问外网,但有一些代理服务器的性能实在难堪大用,经常出现不稳定情况,不同代理服务协议不一样导致传统的Nginx负载均衡没办法做..

背景

实际生活中经常遇到需要挂代理的情况,无论是外网代理还是内网代理,协议通常是HTTP或socks代理(魔法爱国)。

代理经常不具备稳定性,所以不少代理服务商都会提供多个代理以解决单点网络崩溃导致服务崩溃的情况,可事实上手动切换代理是一件非常麻烦事情。

尝试引入过Nginx做负载均衡,但问题是代理协议不一致,而我们通常只需要代理服务,但我们并不需要要求到具体的代理协议是什么,为此可以引入Privoxy将socks5代理服务转换HTTP代理。

再结合Haproxy则可以完美的做到将多个socks合并为一个HTTP代理且实现负载均衡。

配置

首先假设我有5个socks5的代理和5个http代理,socks5代理分别是30000-30004,http代理分别是30006-300010,目标是我们仅需要在其他软件配置一个代理类型为HTTP的代理即可自动使用这10个代理。

以上面的介绍为背景来配置我们的代理负载均衡。

合并代理

首先,5个socks5代理必须转换为http代理,此处显而易见的可以使用Privoxy程序来进行代理协议的转换,但因为Privoxy本身在常见发行版的安装包是自带systemd管理的,如果逐个转换且不说费事,还需要手动写程序运行环境。

更简易的办法,是先使用Haproxy将几个socks5做负载均衡转换为一个socks5代理,然后使用Privoxy将这个端口转换为HTTP代理,最后再使用Haproxy代理这6个HTTP代理

安装并启用haproxy

sudo apt install haproxy
sudo systemctl start haproxy
sudo systemctl enable haproxy

参考下面的Haproxy代理

sudo vim /etc/haproxy/haproxy.cfg

# 下面是配置文件
global
    maxconn 2000         #默认最大连接数

defaults
    mode   tcp           #所处理的类别,默认采用http模式
    option  forwardfor   #将客户端真实ip加到HTTP Header中供后端服务器读取
    option  httpclose    #每次请求完毕后主动关闭http通道,haproxy不支持keep-alive,只>能模拟这种模式的实现
    retries 2            #2次连接失败就认为服务器不可用,主要通过后面的check检查
    option  redispatch   #当serverid对应的服务器挂掉后,强制定向到其他健康服务器
    option  abortonclose #当服务器负载很高时,自动结束掉当前队列中处理比较久的链接
    timeout connect 5000  #连接超时时间
    timeout client  50000 #客户端连接超时时间
    timeout server  50000 #服务器端连接超时时间

frontend socks-in
    mode tcp
    bind 127.0.0.1:30005
    default_backend socks-out

backend socks-out
    mode tcp
    option      tcp-check
    timeout server 3000
    balance roundrobin
    server socks01 127.0.0.1:30000 weight 5 check inter 2000 rise 2 fall 3
    server socks02 127.0.0.1:30001 weight 5 check inter 2000 rise 2 fall 3
    server socks03 127.0.0.1:30002 weight 5 check inter 2000 rise 2 fall 3
    server socks04 127.0.0.1:30003 weight 5 check inter 2000 rise 2 fall 3
    server socks05 127.0.0.1:30004 weight 5 check inter 2000 rise 2 fall 3
    # weight 标示权重,check 标示检查

配置文件简单说明

  • global
    • 全局配置
  • defaults
    • 默认配置(即如果没有特别说明的配置都会采用这个配置)
  • frontend [xxx]
    • 程序流量入口,即代理转换后的其他程序的连接代理的入口
  • backend
    • 程序流量出口,即多个代理的配置项

根据上面的配置文件,我们将30000-30004的socks代理转换负载均衡的的socks代理(30005)了

协议转换

如果将http和socks代理一起配置到socks-out(流量出口)里面会怎么样?实际上,不会报错,但失去了负载均衡的意义,如果你是socks代理Haproxy就会在流量出口中选择代理为socks代理的出口,HTTP代理同理,这与我们一个HTTP代理使用所有协议代理的目标相反了

上面已经使用Haproxy将多个socks代理转换为一个socks代理了,接下来我们安装Privoxy

sudo apt install privoxy
sudo systemctl start privoxy
sudo systemctl restart privoxy

修改Privoxy配置,将socks代理转换为HTTP代理

sudo vim /etc/privoxy/config

# 下面是配置文件,无关的用省略号代替
...
listen-address  0.0.0.0:30011                           # HTTP代理对外监听端口
...
forward-socks5t   /               127.0.0.1:30005 .     # socks代理信息
...

上面的配置将socks5://127.0.0.1:3005的代理转换为 http://127.0.0.1:30011

负载均衡

现在,我们回到Haproxy,我们手里的代理协议已经统一,做负载均衡的方案就非常多了,我个人更倾向于使用Nginx做HTTP代理的负载均衡,关于Nginx的负载均衡请自行Google资料

如果理解第一部分的协议合并,那么Haproxy的负载均衡代理也是一样的,添加如下配置到Haproxy配置文件的末尾

sudo vim /etc/haproxy/haproxy.cfg

# 配置文件
global
    maxconn 2000         #默认最大连接数

defaults
    mode   tcp           #所处理的类别,默认采用http模式
... 
# 上面是在协议合并章节的配置,不需要修改,下面是新增的配置

frontend http-in
    mode http
    bind 127.0.0.1:30015
    default_backend http-out

backend http-out
    mode http
    option      http-check
    timeout server 3000
    balance roundrobin
    server http01 127.0.0.1:30006 check inter 20000
    server http02 127.0.0.1:30007 check inter 20000
    server http03 127.0.0.1:30008 check inter 20000
    server http04 127.0.0.1:30009 check inter 20000
    server http05 127.0.0.1:30010 check inter 20000
    server http06 127.0.0.1:30011 check inter 20000
    # 使用check inter 20秒抓取一次代理情况

我们重启Haproxy,即可得到一个 http://127.0.0.1:30015 的完美HTTP代理

sudo systemctl restart haproxy

附录

Haproxy 2.0.9 - Document


[[replyMessage== null?"发表评论":"发表评论 @ " + replyMessage.m_author]]

account_circle
email
web_asset
textsms

评论列表([[messageResponse.total]])

还没有可以显示的留言...
[[messageItem.m_author]] [[messageItem.m_author]]
[[messageItem.create_time]]
[[getEnviron(messageItem.m_environ)]]
[[subMessage.m_author]] [[subMessage.m_author]] @ [[subMessage.parent_message.m_author]] [[subMessage.parent_message.m_author]]
[[subMessage.create_time]]
[[getEnviron(messageItem.m_environ)]]
目录