# 网络代理
# 代理服务器
:Proxy Server ,用于代替一个主机与其它主机进行通信。
- 工作在会话层,代理应用层的消息。
- 按协议分类:
- SSH 代理
- FTP 代理
- HTTP 代理
- HTTPS 代理
- SOCKS 代理:全称为 SOCKetS ,工作在应用层与传输层之间,比 HTTP 代理更底层、更快。
- SOCKS4 只支持 TCP 连接,而 SOCKS5 还支持 UDP 连接、密码认证。
- FTP、HTTP、SOCKS 代理都是明文通信,而 SSH、HTTPS、shadowsocks 代理是加密通信。
- 按代理反向分类:
- 正向代理 :侧重于代替 client ,向 server 发出访问请求。
- 反向代理 :侧重于代替 server ,接收 client 的访问请求。
- 用途:
- 可以使 client 访问到某些代理服务器才能访问的网络,像 VPN 的功能。
- 可以担任防火墙,过滤 client 发送、接收的数据。
- 可以动态更改将 client 的流量转发到哪个 server ,比如实现负载均衡。
- 可以隔离 server 与 client ,使得 server 不知道 client 的真实 IP 、 client 不知道 server 的真实 IP 。
- 缺点:
- client 的通信数据都要经过代理服务器,可能被监听、篡改。
# Squid
:一个代理服务器,采用 C++ 语言开发。
- 官网 (opens new window)
- 支持 FTP、HTTP、HTTPS 代理协议。
- 常用作简单的 HTTP 正向代理服务器。
- 也可用于反向代理,缓存 HTTP 服务器的响应报文,但比 Nginx 的功能少。
# 部署
- 用 yum 安装:
yum install squid systemctl start squid systemctl enable squid
- 或者用 docker-compose 部署:
version: '3' services: squid: container_name: squid image: sameersbn/squid:3.5.27-2 restart: unless-stopped ports: - 3128:3128 volumes: - ./conf:/etc/squid/
# 配置
用 yum 安装 Squid 时,开启正向代理的步骤:
编辑配置文件
/etc/squid/squid.conf
:http_port 3128 # 定义一个 acl 组,名为 local_ip ,指向源 IP 为 10.0.0.1/24 的流量 # acl local_ip src 10.0.0.1/24 # 定义一个 acl 组,用密码文件进行身份认证 auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwd acl auth_user proxy_auth REQUIRED # 允许指定 acl 组的流量 # http_access allow local_ip http_access allow auth_user # 禁止剩下的所有流量 http_access deny all # 不缓存所有响应报文 cache deny all cache_mem 10MB # 默认会在 HTTP 请求 Headers 中加入 X-Forwarded-For ,声明客户端的真实 IP 。这里删除该 Header forwarded_for delete # 记录访问日志 access_log /var/log/squid/access.log squid # 每隔 30 天翻转一次日志 logfile_rotate 30 # 可选将当前代理的 HTTP 请求,转发给另一个代理服务器,实现代理链 # cache_peer 10.1.1.1 parent 80 0 no-query no-digest # never_direct allow all
生成密码文件:
yum install httpd-tools htpasswd -bc /etc/squid/passwd root ******
测试使用该代理:
systemctl restart squid curl -x http://root:******@127.0.0.1:3128 cip.cc
# SOCKS5
- 用 docker-compose 部署一个 SOCKS5 服务器:
version: '3' services: socks5: container_name: socks5 image: serjs/go-socks5-proxy:v0.0.3 restart: unless-stopped environment: PROXY_USER: root PROXY_PASSWORD: ****** ports: - 1080:1080
- 该镜像采用 Golang 语言开发,详见官方文档 (opens new window)。
# Shadowsocks
:一种基于 SOCKS5 协议的代理协议,简称为 ss ,常用于实现 VPN 。
- 官方文档 (opens new window)
- 支持设置密码、加密传输数据。
- 原理:
- 在一台主机上运行 ss 服务器。
- 在本机运行 ss 客户端,将本机的流量发送到 ss 服务器,被它代理转发。
- ShadowsocksR :简称为 SSR ,是 shadowsocks 的分叉项目。
# Shadowsocks-libev
:一个 ss 代理服务器软件。
- 于 2015 年发布,采用 C 语言开发,于 2020 年停止更新。
- 支持 AEAD Cipher 加密算法。
- 支持 Obfs 混淆,可以将 ss 流量伪装成 http 流量。
- 用 Docker 部署服务器:服务器的命令:
docker run -d --name shadowsocks \ --restart unless-stopped \ -p 8388:8388 \ shadowsocks/shadowsocks-libev:v3.3.5 \ ss-server -s 0.0.0.0 -k ****** -m aes-256-gcm
ss-server # 启动服务器 -c config.json # 使用指定的配置文件 -s 0.0.0.0 # 设置服务器监听的 IP -p 8388 # 设置服务器监听的端口 -k ****** # 设置服务器的认证密码 -m aes-256-gcm # 设置服务器的加密方式 -v # 显示详细日志
# Shadowsocks-rust
:一个 ss 代理服务器软件。
- 用 Docker 部署服务器:配置文件示例:
docker run -d --name ssserver-rust \ --restart unless-stopped \ -p 8388:8388 \ -v /root/shadowsocks-rust/config.json:/etc/shadowsocks-rust/config.json \ ghcr.io/shadowsocks/ssserver-rust:v1.14.3
{ "server": "0.0.0.0", "server_port": 8388, "password": "******", "method": "chacha20-ietf-poly1305", "fast_open": false }
# 客户端
Windows 版 ss 客户端 (opens new window) :
- 运行 ss 客户端之后,它会连接到 ss 服务器,同时在本机监听一个代理端口。
- 本机的进程可以通过 HTTP、Socket 代理协议,将数据发送到该代理端口,然后 ss 客户端会将这些数据转发到 ss 服务器,实现正向代理。
- 也可以开启 ss 客户端的全局模式,代理本机的所有流量。
Linux 版 ss 客户端 :
它是一个命令行工具,功能较少,不能连接多个 ss 服务器,在本机提供的代理端口只支持 Socket 协议。
部署示例:
# 安装 pip3 install shadowsocks # 编辑配置文件 cat > ss.json <<EOF { "server": "10.0.0.1", "server_port": 8388, "local_address": "127.0.0.1", "local_port": 8388, "password": "******", "timeout": 5, "method": "aes-256-cfb" } EOF # 启动客户端 sslocal -c ss.json -d start
一个 sslocal 客户端只能连接一个 ss 服务器。
可以再运行代理服务器 privoxy ,监听一个 HTTP 代理端口,将该端口的流量转发到 Socket 代理端口。
# 安装 yum install -y privoxy systemctl start privoxy systemctl enable privoxy # 编辑配置文件 sed '/listen-address 127.0.0.1:8118/d' /etc/privoxy/config -i cat >> /etc/privoxy/config <<EOF listen-address 0.0.0.0:8118 # 将 HTTP 请求转发到该代理 forward-socks5 / 127.0.0.1:8388 . # 第一个字段为 url_pattern ,取值为 / 则匹配所有 HTTP 请求 # 第二、三个字段为代理、父级代理,取值为 . 则表示忽略 # 不代理这些 HTTP 请求 forward 10.*.*.*/ . forward 127.*.*.*/ . forward 172.16.*.*/ . forward 192.168.*.*/ . EOF # 重启 systemctl restart privoxy
试用该代理:
curl -x 127.0.0.1:8118 google.com
# V2Ray
:一个代理服务器,比 ss 的功能更多。
- GitHub (opens new window)
- 于 2019 年发布,采用 Goalng 语言开发。是 Project V 社区研发的主要软件,后来改名为 v2fly 。
- V2Ray 服务器的流量分为两个方向:
- inbounds :入站流量,即客户端发送到 V2Ray 的流量。
- 客户端可使用 V2Ray 原创的 VMess 代理协议,也兼容 HTTP、Shadowsocks 等代理协议。
- outbounds :出站流量,即 V2Ray 将客户端的流量转发到某个网站。
- inbounds :入站流量,即客户端发送到 V2Ray 的流量。
- 用 Docker 部署服务器:配置文件示例:
docker run -d --name v2fly \ --restart unless-stopped \ -v /root/v2fly/config.json:/etc/v2fly/config.json \ -p 80:80 \ v2fly/v2fly-core:v5.1.0 \ run -c /etc/v2fly/config.json
{ "inbounds": [{ "port": 80, "protocol": "vmess", "settings": { // 只允许这些 id 的客户端连接 "clients": [{ "id": "******" }] } }], "outbounds": [{ "protocol": "freedom", "settings": {} }] }
- 在 Windows 上常用的客户端软件是 v2rayN (opens new window) 。
# Trojan
:一个代理服务器。能加密通信,并伪装成互联网常见的 HTTPS 流量。
- 于 2019 年发布,采用 C++ 语言开发。
# 代理客户端
- 有的程序不支持使用代理,有的程序只支持使用 HTTP 等简单的代理协议。因此建议安装一个专用的代理客户端,通过两种方式代理其它程序的流量:
- 透明代理(Transparent proxy):
- 拦截其它程序发出的流量,转发到代理服务器。其它程序不会感知到代理,不需要主动使用代理。
- 转换代理协议:
- 通过某种代理协议连接到代理服务器,再在本机监听一个采用 HTTP 等简单代理协议的端口,将该端口收到的流量转发到代理服务器。
- 此时,具有代理功能的程序,一般都能通过该端口使用代理。但没有代理功能的程序,依然不能使用代理。
- 透明代理(Transparent proxy):
# Proxifier
:一个 GUI 工具,用作代理客户端,收费。
- 特点:
- 支持 Windows、MacOS 系统,不支持 Linux 。
- 支持 HTTP、HTTPS、SOCKS4、SOCKS5 代理协议。
- 支持透明代理。原理如下:
- Windows 系统上,一般程序需要调用 Winsock API 进行 Socket 通信。
- Winsock 提供了 LSP(Layered Service Provider) 功能:允许程序自定义一个 LSP DLL 库,在一般程序调用 Winsock API 时被加载,从而可以劫持其流量。
- 支持灵活的代理规则:将某个程序发向某 IP:Port 的 TCP 包,转发到某个代理服务器。支持通配符。
- 支持用多个代理服务器组成代理链。
- 用法:
- 安装 Proxifier 并启动。
- 添加代理服务器。
- 添加代理规则。
- 保持 Proxifier 运行,即可代理本机程序的流量。
# ProxyChains
:一个 Unix 系统的命令行工具,采用 C 语言开发,用作代理客户端。
- GitHub (opens new window)
- 支持透明代理。原理如下:
- 声明环境变量 LD_PRELOAD ,让程序在导入 DLL 库时,优先导入 libproxychains4.so 库。
- 在 libproxychains4.so 库中,重写关于 Socket 通信的函数,将程序发出的 TCP 流量转发到代理服务器。
- 缺点:
- 只能代理 TCP 流量,不支持 UDP、ICMP 。
- 只能代理指定的程序,不能代理系统所有进程。
- 只能代理采用动态链接库的程序。
- Chrome 浏览器在沙盒中运行网页,也不会被代理。
# 部署
- 安装:
wget https://github.com/rofl0r/proxychains-ng/archive/refs/tags/v4.14.tar.gz tar -zxvf v4.14.tar.gz cd proxychains-ng-4.14 ./configure --prefix=/usr --sysconfdir=/etc make make install
- 编辑配置文件 /etc/proxychains.conf ,示例:
quiet_mode # 安静模式,运行时不输出过程信息 dynamic_chain # 自动选用 ProxyList 中可用的代理,且按顺序 proxy_dns # 将 DNS 请求也代理 # 取消代理发向指定 IP 的数据包 localnet 127.0.0.0/255.0.0.0 localnet 10.0.0.0/255.0.0.0 localnet 172.16.0.0/255.240.0.0 localnet 192.168.0.0/255.255.0.0 # 发送数据包时,修改目标 IP:Port dnat 1.1.1.1:80 1.1.1.2:443 dnat 1.1.1.1:443 1.1.1.2 dnat 1.1.1.1 1.1.1.2 # 声明一组代理服务器,支持 HTTP、SOCKS4、SOCKS5 代理协议,支持设置账号密码 [ProxyList] http 127.0.0.1 3128 socks5 127.0.0.1 1080 root ******
- 执行命令:
proxychains4 curl cip.cc # 在代理下执行一条命令 proxychains4 bash # 创建一个 shell ,在其中执行的命令都采用代理
# redsocks
:一个 Linux 系统的命令行工具,采用 C 语言开发,用作代理客户端。
- GitHub (opens new window)
- 支持透明代理。原理如下:
- redsocks 连接到代理服务器,并在本机监听一个端口,将该端口收到的流量转发到代理服务器。
- 用户手动配置 iptables 防火墙规则,将本机发出的 TCP 流量重定向到 redsocks 端口。
- 缺点:
- 需要手动配置 iptables 规则,比较麻烦。
- 有些程序可能无视 iptables 规则。
# 部署
- 用 apt 安装:或者手动编译后安装:
apt install redsocks
git clone https://github.com/darkk/redsocks cd redsocks make cp redsocks /usr/bin/redsocks
- 编辑配置文件 /etc/redsocks.conf ,示例:
base { log_debug = off; log_info = on; log = stderr; # 日志的保存位置,可改为 "file:/var/log/redsocks.log" 文件 daemon = on; redirector = iptables; } redsocks { // 在本机监听的端口 local_ip = 127.0.0.1; local_port = 12345; // 要连接的代理服务器 ip = 10.0.0.1; port = 1080; type = socks5; login = <username>; password = <password>; }
- 可以定义多个 redsocks{} 代理配置。
- 用 systemctl 保持运行:或者手动启动:
systemctl restart redsocks systemctl enable redsocks
redsocks -c /etc/redsocks.conf
- 添加 iptables 规则:系统重启时会重置 iptables 规则。因此建议将配置 iptables 的命令保存为一个 shell 脚本,每次系统重启时执行它。
iptables -t nat -A OUTPUT -p tcp -d 192.168.1.0/24 -j REDIRECT --to-ports 12345 # 编辑 nat 表,将本机发出的某些流量重定向 REDSOCKS 端口 iptables -t nat -L OUTPUT # 查看 iptables 规则
# Clash
:一个通用的代理客户端,采用 Golang 语言开发。
- GitHub (opens new window)
- 支持 HTTP、SOCKS、Shadowsocks、Vmess 等多种代理协议。
- 支持 Linux、MacOS、Windows、Android 系统。
- 在 Linux 系统上支持透明代理。
- 原理与 redsocks 类似,需要手动配置 iptables 规则。
# 反向代理
实现反向代理的常见工具:
- LVS
- :可实现第四层的 TCP/UDP 代理。
- F5
- :一个通过硬件实现负载均衡的服务器,基于 BIG-IP 协议。
- HAProxy
- :一个反向代理服务器,可实现第四层的 TCP 代理、第七层的 HTTP 代理。
- Nginx
- :一个反向代理服务器,可实现第四层的 TCP 代理、第七层的 HTTP 代理。
- keepalived
- :基于 IPVS 技术 ,可实现第四层的 TCP/UDP 代理。
- frp
# LVS
:Linux 虚拟服务器(Linux Virtual Server),是 Linux 的一个内核模块,通过转发 TCP/UDP 数据包,实现第四层的反向代理。
LVS 工作在内核态,比 Nginx 等用户态代理的性能更高。
原理:
- 创建一些 IPVS(IP Virtual Server)作为负载均衡器。
- 每个 IPVS 绑定一个 Virtual IP ,称为 VIP 。
- 每个 IPVS 负责将将访问 VIP 的 TCP、UDP 流量反向代理到某些后端的 IP 。这里将后端称为 Real Server 。
- 配置 iptables 规则,将访问 VIP 的流量交给 IPVS 处理。
- 创建一些 IPVS(IP Virtual Server)作为负载均衡器。
有多种反向代理模式:
- DR 模式(direct routing)
- 原理:改写请求报文的目标 MAC 地址,将直接它转发给 Real Server 。而 Real Server 直接返回响应报文给 client ,不经过 IPVS 。
- 优点:
- 代理速度最快。
- 缺点:
- IPVS 所在的主机 IP ,与 Real Server IP ,必须位于同一个 VLAN 子网,否则不能将请求报文转发到 Real Server 。
- 转换请求报文时不能修改目标端口,因此反向代理时不支持端口映射。假设 Real Server 监听的端口是 80 ,则 IPVS 监听的端口也只能是 80 。
- NAT 模式
- 原理:
- client 发出请求报文,dst_ip 为 IPVS 的 VIP ,src_ip 为 client_ip 。
- IPVS 收到请求报文,进行 DNAT ,将 dst_ip 改为 Real Server IP 。然后转发给 Real Server 。
- Real Server 收到请求报文,返回响应报文,dst_ip 为 client_ip ,src_ip 为 Real Server IP 。
- IPVS 收到响应报文,进行 SNAT ,将 src_ip 改为 VIP 。然后转发给 client 。
- 优点:
- 实现了透明代理。
- 缺点:
- 请求报文、响应报文都要经过 IPVS 处理,因此代理速度较慢。
- 需要将 VIP 配置为 Real Server 主机的网关,否则 Real Server 的响应报文的 dst_ip 为 client_ip ,会直接发给 client ,不会经过 IPVS 的 SNAT 。这也限制了 IPVS 与 Real Server 必须位于同一个子网。
- 原理:
- TUN 模式
- 原理:
- IPVS 将 client 的请求报文,封装成新的 IP 包,dst_ip 为 Real Server IP 。然后转发给 Real Server 。
- Real Server 收到 IP 包,解包之后发现这些数据是 IPVS 发来的,还知道了 client_ip ,于是直接将响应报文发送给 client 。
- 优点:
- 支持 IPVS 与 Real Server 位于不同子网。
- 响应报文不经过 IPVS ,因此性能比 NAT 模式高。
- 缺点:
- 需要 Real Server 所在主机支持 IP Tunneling 协议,才能解包。
- 原理:
- DR 模式(direct routing)
支持多种负载均衡算法:
rr # round robin(轮询),将请求报文轮流转发给各个后端,使得每个后端收到的请求数差不多相等。这是默认策略 wrr # weight round robin(加权轮询),给每个后端设置权重,权重更大的后端,更大概率收到请求 sh # source hashing ,计算请求报文的源 IP 的哈希值,将哈希值相同的请求转发给同一个后端 dh # destination hashing ,计算报文的目标 IP 的哈希值 lc # least connection(最少连接),监控每个后端的当前 TCP 连接数,将请求转发给连接数最少的后端 wlc # weight least connection(加权的 lc ) lblc # locality based least connections(基于局部的最少连接),记录每个请求的目标 IP 上一次使用的后端,作为转发规则,如果目标后端负载过大,则采用 lc 算法 lblcr # locality based least connections with replication(带复制的 lblc ),记录每个请求的目标 IP 使用的一组后端,采用 lc 从组中选出一个后端 sed # shortest expected delay ,监控每个后端的平均响应耗时,将请求转发给耗时最短的后端 nq # never queue ,优先将请求转发给当前连接数为 0 的后端,如果不存在这样的后端,则采用 sed 算法
可安装 ipvsadm 命令来管理 IPVS 。
ipvsadm -A # 新增 IPVS -D # 删除 IPVS -L # 列出所有 IPVS -n # 将 ip、port 显示成数字,而不是服务名 -t <vip:port> # --tcp-service ,指定 IPVS 监听的地址 -u <vip:port> # --ucp-service -r <ip:port> # --real-server ,指定 IPVS 反向代理的后端 -s rr # --scheduler ,负载均衡算法 -w <int> # --weight ,指定 real-server 的权重 -p 300 # --persistent ,如果某个 client_ip 多次发出请求,间隔不超过该时长,则会被转发到同一个 real-server # 反向代理模式 -g # --gatewaying ,DR 模式,这是默认模式 -m # --masquerading ,NAT 模式 -i # --ipip ,TUN 模式
- 例:
ipvsadm -Ln ipvsadm -A -t 10.0.0.1:80 -s rr # 新增一个 IPVS ,监听地址为 10.0.0.1:80 ,负载均衡算法为 rr ipvsadm -a -t 10.0.0.1:80 -r 10.0.0.2:80 -m # 在 IPVS 中新增一条规则,反向代理 10.0.0.2:80 ,反向代理模式为 NAT
- 例:
# keepalived
:一个命令行工具,用于实现高可用的反向代理。
- GitHub (opens new window)
- 原理:
- 基于 IPVS 技术,反向代理多个 upstream 实例,支持健康检查。
- 可部署多个 keepalived 实例,基于 VRRP 协议实现高可用。
- 用途:
- 常见的反向代理方案如下:
- 网站部署一个 upstream 实例时,如果故障,用户就访问不了。通常部署一组 upstream 实例,用 Nginx 反向代理。用户只需访问 Nginx ,访问流量会被 Nginx 被转发到某个 upstream 实例。
- Nginx 支持对这些 upstream 进行健康检查,只将流量转发到健康的 upstream 实例。即使个别 upstream 实例故障,用户依然能正常访问 Nginx 。
- 上述方案实现了 upstream 的高可用,但 Nginx 本身存在单点故障的风险。
- 虽然 Nginx 很少故障,但 Nginx 所在主机可能因为断电等原因宕机。
- 即使在多个主机上分别部署一个 Nginx 实例,但域名只能解析到一个主机 IP ,并不能实现 Nginx 的高可用。
- 可使用 keepalived 实现高可用的反向代理:
- 在至少 2 个主机上分别部署一个 Nginx 实例。(也可省略 Nginx ,让 keepalived 直接反向代理 upstream )
- 在至少 2 个主机上分别部署一个 keepalived 实例,反向代理上述一组 Nginx 。
- 这组 keepalived 实例,相互之间通过 VRRP 协议通信,自动选举出一个当前可用的 keepalived 实例,担任 MASTER 节点,其它实例担任备用节点。
- MASTER 节点会广播 Gratuitous ARP 消息,将一个 VIP 解析到自己的 Mac 地址。当前子网的其它主机发送请求到 VIP 时,实际上是发送到 MASTER 节点。
- 当 MASTER 节点故障时,会自动选举一个备用节点,担任新的 MASTER 节点,并将 VIP 解析到新的 MASTER 节点,因此其它主机能继续访问 VIP 。
- Nginx 等代理工具只能实现 upstream 的高可用(负载均衡+健康检查+故障转移),不能实现自身的高可用。而 keepalived 代理工具能基于 VRRP 协议实现自身的高可用。
- 公有云平台一般不支持传播 ARP 消息,因此不能使用 keepalived 方案。
- 常见的反向代理方案如下:
# 部署
在一个主机上安装:
yum install keepalived systemctl start keepalived systemctl enable keepalived
编辑配置文件
/etc/keepalived/keepalived.conf
:# 全局配置 global_defs { # router_id 10.0.0.1 # 该 VRRP 节点的名称,一般配置为主机 IP ,也可省略 fBvrrp_skip_check_adv_addr # 检查 VRRP 广播中的所有地址可能耗时久,如果重复收到主路由器的多次广播,则跳过检查 # vrrp_strict # 是否严格遵守 VRRP 协议,比如至少分配一个 VIP 、不支持 ping VIP 。建议注释该配置 # vrrp_garp_master_repeat 5 # 当 MASTER 节点刚刚当选时,开始第一轮广播,广播几遍 Gratuitous ARP 消息 # vrrp_garp_master_delay 5 # 当 MASTER 节点刚刚当选时,等几秒开始第二轮广播。如果配置为 0 ,则不会第二轮广播 # vrrp_garp_master_refresh 0 # 当 MASTER 节点运行时,每隔几秒广播一轮 Gratuitous ARP 消息。默认配置为 0 ,表示只有第一轮、第二轮广播 # vrrp_garp_master_refresh_repeat 1 # 每轮广播几遍 Gratuitous ARP 消息 # vrrp_garp_interval 0 # 广播 Gratuitous ARP 消息时,间隔几秒 # preempt_delay 0 # 当前节点启动时,收到 VRRP 广播 ,如果发现自己的 priority 比已有的 MASTER 节点高,则会抢占 MASTER 角色。可延迟几秒才抢占,避免频繁切换 MASTER } # 配置该 keepalived 所属的 VRRP 集群,名称为 VI_1 # 一个子网内可部署多个 VRRP 集群,每个 VRRP 集群称为一个 vrrp_instance ,包含多个 VRRP 节点 # 这里不需要配置所有 VRRP 节点的 IP 。因为每个 VRRP 节点会通过局域网广播,自动发现其它 VRRP 节点,并相互通信 # 如果几个节点的 virtual_router_id 相同,则属于同一集群,会自动选举出 MASTER 节点 vrrp_instance VI_1 { # state MASTER # 该 keepalived 的初始状态,可担任 MASTER 或 BACKUP 节点,也可省略该配置,让它自动选举 interface eth0 # 工作在哪个网口 virtual_router_id 51 # 该 VRRP 节点所属的虚拟路由器的 id priority 100 # 该 VRRP 节点的优先级。一组 VRRP 节点的优先级应该各不相同,优先级最高的节点,总是会被选举为 MASTER 节点 advert_int 1 # 每隔几秒广播一次 VRRP 消息,给其它 VRRP 节点 authentication { # VRRP 节点之间的身份认证 auth_type PASS auth_pass ****** # 密码,最多 8 个字符 } # 可分配多个 VIP ,会自动绑定到 MASTER 节点的网口 # VIP 必须与当前主机 IP 位于同一子网,因为其它主机只会对当前子网内的 IP 进行 ARP 查询 virtual_ipaddress { 10.0.0.10 # 10.0.0.11 } } # 让 keepalived 运行一个虚拟服务器,监听 VIP 的一个端口,反向代理一组 real_server virtual_server 10.0.0.10 80 { delay_loop 5 # 每隔几秒执行一次健康检查 lb_algo wrr # 负载均衡算法,参考 LVS 的配置 lb_kind NAT # 反向代理模式,参考 LVS 的配置 persistence_timeout 60 # LVC 的持久超时。如果某个 client_ip 多次发出请求,间隔不超过该时长,则会被转发到同一个 real_server protocol TCP # 代理协议,可选 TCP 或 UDP # sorry_server 10.0.0.2 80 # 如果所有 real_server 都未通过健康检查,则将流量转发到该 server real_server 10.0.0.1 80 { weight 1 # 该 real_server 的权重 # 健康检查的方式,可选 HTTP_GET、SSL_GET 等 HTTP_GET { # 可改为 SSL_GET url { # 可对多个 url 进行健康检查 path /test status_code 200-299 301-302 401 # 向指定 url 发出 HTTP GET 请求,然后检查响应的状态码。默认配置为 status_code 200-299 # digest 640205b7b0fc66c1ea91c463fac6334d # 还可检查响应的 MD5 哈希值 } url { path /test2 } connect_timeout 3 # 连接超时 nb_get_retry 3 # 重试次数 delay_before_retry 3 # 重试间隔 } # TCP_CHECK { # connect_port 80 # connect_timeout 3 # } # MISC_CHECK { # 执行 shell 脚本来健康检查 # misc_path "/path_to_script/script.sh <arg_list>" # } } real_server 10.0.0.2 80 { weight 1 TCP_CHECK { connect_port 80 connect_timeout 3 } } } # 可定义多个虚拟服务器 virtual_server 10.0.0.10 443 { ... }
- 修改配置文件之后,执行
systemctl start keepalived
重启才会生效。 - 查看日志:
[root@CentOS ~]# tail -f /var/log/messages | grep Keepalived Aug 12 12:26:53 [localhost] Keepalived_vrrp[323]: VRRP_Instance(VI_1) Transition to MASTER STATE # 该节点属于 VI_1 集群,变为 MASTER 状态 Aug 12 12:26:54 [localhost] Keepalived_vrrp[323]: VRRP_Instance(VI_1) Entering MASTER STATE Aug 12 12:26:54 [localhost] Keepalived_vrrp[323]: VRRP_Instance(VI_1) setting protocol VIPs. Aug 12 12:26:54 [localhost] Keepalived_vrrp[323]: Sending gratuitous ARP on eth0 for 10.0.0.10 # 广播 Gratuitous ARP 消息 Aug 12 12:26:54 [localhost] Keepalived_vrrp[323]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on eth0 for 10.0.0.10 # 第一轮广播 Aug 12 12:26:59 [localhost] Keepalived_vrrp[323]: Sending gratuitous ARP on eth0 for 10.0.0.10 Aug 12 12:26:59 [localhost] Keepalived_vrrp[323]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on eth0 for 10.0.0.10 # 第二轮广播 Aug 12 12:27:04 [localhost] Keepalived_vrrp[323]: Sending gratuitous ARP on eth0 for 10.0.0.10
- 执行
ip addr show eth0
查看网口,是否绑定了 VIP 。 - 在同一子网的其它主机可以 ping 通 VIP ,或者 curl 访问 VIP 的端口。但不能使用 traceroute 命令定位 VIP ,因为 VIP 没有路由。
- 可以只配置 vrrp_instance ,不配置 virtual_server 反向代理。相当于给当前主机增加了 VIP ,供其它主机访问。
- 修改配置文件之后,执行
重复上述步骤,在第二台主机上部署一个 keepalived ,配置相同,只是 priority 为 99 。
- 建议停止主机的 firewalld ,以免阻断各节点之间的 VRRP 通信。
- 停止第一台主机,然后检查第二台主机,它会自动切换成 MASTER 角色,并绑定 VIP 。
- 重启第一台主机,它的 priority 最高,会抢占 MASTER 角色,并绑定 VIP ,日志如下:
Aug 12 12:36:21 [localhost] Keepalived_vrrp[413]: VRRP_Instance(VI_1) Received advert with lower priority 99, ours 100, forcing new election Aug 12 12:27:04 [localhost] Keepalived_vrrp[413]: Sending gratuitous ARP on eth0 for 10.0.0.10
- 同时应该只有一台主机的网口绑定 VIP 。如果多台主机绑定同一个 VIP ,则该 VIP 解析到的 Mac 地址不固定,会增加 TCP 丢包率。
# frp
:一个命令行工具,提供了反向代理、内网穿透的功能。
- GitHub (opens new window)
- 采用 Golang 语言开发。
- 支持 TCP、UDP、HTTP、HTTPS 等多种代理协议。
- 采用 C/S 架构工作。
- frps :服务器,部署在任一主机上,不需访问外部,只需被 frpc、用户访问。
- frps 所在主机通常拥有一个固定的外网 IP ,供外网用户访问。
- 用户向 frps 发送网络包时,会先被 frps 转发到 frpc ,再被 frpc 转发到内网服务。
- frpc :客户端,部署在任一主机上,不需被外部访问,只需访问到 frps、内网服务。
- frps :服务器,部署在任一主机上,不需访问外部,只需被 frpc、用户访问。
例:
登录一台主机,下载 frp 的发行版,编辑配置文件 frps.ini :
[common] bind_port = 7000 # 让 frps 监听一个端口,供 frpc 访问,用于它们内部通信 token = xxxxxx # 用于 frpc 与 frps 之间的认证
启动服务器:
./frps -c frps.ini
或者用 docker-compose 部署:
version: '3' services: frps: container_name: frps image: snowdreamtech/frps:0.37.0 restart: unless-stopped ports: - 7000:7000 volumes: - ./frps.ini:/etc/frp/frps.ini
登录另一个主机,编辑配置文件 frpc.ini :
[common] server_addr = 1.1.1.1 # frps 的地址 server_port = 7000 token = xxxxxx # 定义一个反向代理,名称自定义 [proxy1] type = tcp # 代理的类型 local_ip = 10.0.0.1 local_port = 80-90,443 remote_port = 80-90,443 # 让 frps 监听 remote_port 端口,供用户访问,并将该端口收到的网络包转发到 local_ip:local_port # bandwidth_limit = 1MB # 限制带宽,默认无限制 # use_compression = false # frpc 与 frps 之间通信时,是否压缩 # use_encryption = false # frpc 与 frps 之间通信时,是否加密 # 可以定义多个反向代理 [proxy2] ...
启动客户端:
./frpc -c frpc.ini
或者用 docker-compose 部署:
version: '3' services: frpc: container_name: frpc image: snowdreamtech/frpc:0.37.0 restart: unless-stopped volumes: - ./frpc.ini:/etc/frp/frpc.ini
让用户访问 frps 的反向代理端口:
curl 1.1.1.1:10080
# VPN
:虚拟私有网络(Virtual Private Network),指由公网上的几台主机组成一个虚拟的私有网络。
- VPN 是一个私有网络。几个主机虽然通过公网通信,但数据包会加密传输,只有加入 VPN 网络的主机才能解密。
- VPN 常用于实现正向代理。比如某个机房的各个服务器不暴露 SSH 端口到公网,但机房的网关暴露 SSH 端口到公网,用户可通过公网 SSH 登录该网关,然后间接 SSH 登录该机房的内网服务器。
- VPN 软件与代理软件类似,但区别在于:
- VPN 软件通常会将两个主机在网络层连通,比如可以 ping 通。而代理软件通常会将两个主机在传输层连通,不能 ping 通,可以 curl 访问端口。
- VPN 软件默认会对主机上所有流量进行透明代理。而代理软件默认不开启透明代理,甚至不一定支持透明代理功能。