背景
20条宽带出口实现20个独立IP的代理服务,如用户从出口A访问进来,代理服务也必须是使用出口A去访问被代理的服务。
涉及资源
交换机:华为 S5735S-L48TAS-A *1
路由:Mikrotik RB5009UG+S+(v7.2.3) *1
服务器:CentOS7.9 *1
ISP: 电信(PPPoE拨号) * 40
涉及技术点
交换机:VLAN、Trunk、链路聚合等
软路由:SNAT、DNAT、Bridge、策略路由等
代理服务器: nginx(HTTP代理)、dante(Socks5代理)
网段规划
内网网关:172.16.255.1/24
代理服务器:
172.16.255.101/24 <-> pppoe-out01
172.16.255.102/24 <-> pppoe-out02
...
172.16.255.140/24 <-> pppoe-out40
部署要略
交换机设备
根据软规则对交换机进行如下端口规划:
序号 | 端口号 | VLAN | 备注 |
---|---|---|---|
1 | GE 0/0/1 | 101 | pppoe-out01 |
2 | GE 0/0/2 | 102 | pppoe-out02 |
3 | GE 0/0/3 | 103 | pppoe-out03 |
... | |||
40 | GE 0/0/40 | 140 | pppoe-out40 |
21 | GE 0/0/45 | - | 聚合链路成员接口 |
22 | GE 0/0/46 | - | 聚合链路成员接口 |
23 | GE 0/0/47 | - | 聚合链路成员接口 |
24 | GE 0/0/48 | - | 聚合链路成员接口 |
Mikrotik RouterOS设备
创建聚合接口
创建脚本
/interface bonding add arp=enabled arp-interval=100ms disabled=no mode=802.3ad mtu=1500 name=bond0 primary=none \ slaves=ether7,ether8,ether5,ether6
基于聚合接口创建vlan子接口
创建脚本
:for no from=1 to=9 do={ /interface vlan add interface=bond0 mtu=1500 name=("vlan1".$no use-service-tag=no vlan-id=("10".$no) } :for no from=10 to=40 do={ /interface vlan add interface=bond0 mtu=1500 name=("vlan1".$no use-service-tag=no vlan-id=("1".$no) }
基于聚合接口创建bridge接口
新增专用bridge接口,脚本如下(部分省略):
<...> :for no from=10 to=40 do={ /interface bridge add admin-mac=("E4:8D:8C:1D:25:".$no) ageing-time=5m arp=enabled arp-timeout=auto auto-mac=no dhcp-snooping=no disabled=no fast-forward=no igmp-snooping=no mtu=auto name=("ct-".$no) }
将vlan接口添加到对应的bridge接口
脚本如下(部分省略)
<...> :for no from=41 to=60 do={ /interface bridge port add auto-isolate=no bpdu-guard=no bridge=("ct-".$no) interface=("vlan1".$no) internal-path-cost=10 learn=auto pvid=1 restricted-role=no restricted-tcn=no tag-stacking=no trusted=no unknown-multicast-flood=yes unknown-unicast-flood=yes }
创建pppoe拨号接口
脚本如下(部分省略)
/interface pppoe-client add add-default-route=yes allow=pap,chap,mschap1,mschap2 default-route-distance=2 dial-on-demand=no disabled=no interface=ct-01\ name=pppoe-out01 profile=default use-peer-dns=no user=USERNAME add add-default-route=yes allow=pap,chap,mschap1,mschap2 dial-on-demand=no disabled=no interface=ct-02\ name=pppoe-out01 profile=default use-peer-dns=no user=USERNAME <...>
策略路由
每个源IP需要保证固定出口,所以我们需要使用策略路由来实现,大致方法就是根据源IP去决定走哪个出口,实现如下:
脚本如下(部分省略)
创建路由表
... :for no from=10 to=40 do={ /routing table add name=("proxy".$no) fib }
玛德,规则软过头了
在Mangle表中的Prerouting链定义源IP并生成20个路由表
... :for no from=10 to=40 do={ /ip/firewall/mangle add src-address=("172.16.255.1".$no) chain=prerouting action=mark-routing new-routing-mark=("proxy".$no) passthrough=yes }
根据创建好的路由表,添加路由
... :for no from=10 to=40 do={ /ip/route add dst-address=0.0.0.0/0 gateway=("pppoe-out".$no) routing-table=("proxy".$no) }
规则下次适度软下就好了。
创建SNAT规则
... :for no from=10 to=40 do={ /ip firewall nat add action=masquerade chain=srcnat out-interface=("pppoe-out".$no) src-address=("172.16.255.1".$no) }
创建DNAT规则
<...> :for no from=41 to=60 do={ /ip firewall nat add chain=dstnat action=dst-nat to-addresses=("172.16.255.1".$no) to-ports=3014 protocol=tcp src-address-list=src-access-proxy in-interface=("pppoe-out".$no) dst-port=3014 log=no } <...> :for no from=41 to=60 do={ /ip firewall nat add chain=dstnat action=dst-nat to-addresses=("172.16.255.1".$no) to-ports=3015 protocol=tcp src-address-list=src-access-proxy in-interface=("pppoe-out".$no) dst-port=3015 log=no }
因未配置用户名密码且客户都是固定IP,所以定义了一个源地址访问地址列表:src-access-proxy
代理服务器
多IP配置
往`/etc/sysconfig/network-scripts/ifcfg-eth0文件中加入以下内容:
IPADDR1=172.16.255.102 PREFIX1=24 ... IPADDR59=172.16.255.60 PREFIX59=24
快速生效
# nmcli conn reload # nmcli conn up eth0
socks5代理
批量生成配置文件、systemd服务
#!/usr/bin/env bash prefix=172.16.255 port=3014 for no in {101..140} do cat > /etc/sockd_$no.conf<<EOF logoutput: syslog user.privileged: root user.unprivileged: nobody internal: $prefix.$no port=$port external: $prefix.$no socksmethod: none clientmethod: none client pass { from: 0.0.0.0/0 to: 0.0.0.0/0 log: connect disconnect error } socks pass { from: 0.0.0.0/0 to: 0.0.0.0/0 log: error } EOF cat > /usr/lib/systemd/system/sockd_$no.service<<EOF [Unit] Description=Dante SOCKS proxy After=network-online.target [Service] Type=simple ExecStart=/usr/sbin/sockd -f /etc/sockd_$no.conf StandardOutput=syslog StandardError=syslog LimitNPROC=infinity LimitNOFILE=10240 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF systemctl start sockd_$no.service systemctl enable sockd_$no.service done
查看端口监听状态
# ss -tln |grep 3014 LISTEN 0 511 172.16.255.140:3014 *:* ... LISTEN 0 511 172.16.255.103:3014 *:* LISTEN 0 511 172.16.255.102:3014 *:* LISTEN 0 511 172.16.255.101:3014 *:*
HTTP代理
http代理第一闪现的是squid,经过测试squid在单节点多IP的场景不受控制,遂转入到nginx,使用以下脚本快速生成配置文件
prefix=172.16.255 for no in {101..140} do cat >/opt/nginx/conf/conf.d/$no.conf<<EOF server { listen $prefix.$no:3015; # forward proxy for CONNECT request proxy_connect; proxy_connect_allow all; proxy_connect_connect_timeout 30s; proxy_connect_read_timeout 90s; proxy_connect_send_timeout 90s; proxy_connect_bind $prefix.$no; location / { proxy_pass \$scheme://\$http_host\$request_uri; proxy_bind $prefix.$no; } access_log /var/log/nginx/${no}_access.log combined buffer=64k flush=1m; } EOF done
测试
测试脚本
#!/usr/bin/env bash proxy_ips=( IP1 IP2 ... IP40 ) url=${1:-myip.ipip.net} echo "[+] socks5 proxy testing" for ip in ${proxy_ips[@]} do echo "[-]$ip testing result: $(curl -s /dev/null --connect-timeout 3 -x socks5://$ip:3014 $url)" done echo "[+] http proxy testing" for ip in ${proxy_ips[@]} do echo "[-]$ip testing result: $(curl -s /dev/null --connect-timeout 3 -x socks5://$ip:3015 $url)" done
测试结果:代理IP的返回来的IP一致。
后续
DDNS
由于是当前是使用IP,可以使用域名来绑定出口。
问题答疑
1、代理服务器重启后,有几个socks 地址代理失败,经过查看,失败是因为系统未监听该端口,查看日志,内存资源分配失败导致,当前虚拟机内存1G。加资源管上。
推荐本站淘宝优惠价购买喜欢的宝贝:
本文链接:https://sg.hqyman.cn/post/9548.html 非本站原创文章欢迎转载,原创文章需保留本站地址!
休息一下~~