# 网络代理

# 代理服务器

:Proxy Server ,用于代替一个主机与其它主机进行通信。

  • 工作在会话层,代理应用层的消息。
  • 按协议分类:
    • SSH 代理
    • FTP 代理
    • HTTP 代理
    • HTTPS 代理
    • SOCKS 代理:全称为 SOCKetS ,工作在应用层与传输层之间,比 HTTP 代理更底层、更快。
      • SOCKS4 只支持 TCP 连接,而 SOCKS5 还支持 UDP 连接、密码认证。
      • FTP、HTTP、SOCKS 代理都是明文通信,而 SSH、HTTPS、shadowsocks 代理是加密通信。
  • 按代理反向分类:
    • 正向代理 :侧重于代替客户端,向服务器发出访问请求。
    • 反向代理 :侧重于代替服务器,接收客户端的访问请求。
  • 用途:
    • 可以隔离服务器与客户端的联系,隐藏双方的信息。
    • 可以使客户端访问到某些代理服务器才能访问的网络。
    • 可以担任防火墙,过滤客户端发送、接收的数据。
    • 可以动态更改将客户端的流量转发到哪个服务器,比如实现负载均衡。
  • 缺点:
    • 客户端的通信数据都要经过代理服务器,可能被监听、篡改。

# 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 时,开启正向代理的步骤:

  1. 编辑配置文件 /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
    
    # 默认会在 HTTP 请求 Headers 中加入 X-Forwarded-For ,声明客户端的真实 IP 。这里删除该 Header
    forwarded_for delete
    
    # 记录访问日志
    access_log /var/log/squid/access.log squid
    # 每隔 30 天翻转一次日志
    logfile_rotate 30
    
  2. 生成密码文件:

    yum install httpd-tools
    htpasswd -cb /etc/squid/passwd leo ******
    
  3. 测试使用该代理:

    systemctl restart squid
    curl -x http://leo:******@127.0.0.1:3128 cip.cc
    

# SOCKS5

  • 用 docker-compose 部署一个 SOCKS5 服务器:
    version: '3'
    
    services:
      socks5:
        container_name: socks5
        image: serjs/go-socks5-proxy
        restart: unless-stopped
        environment:
          PROXY_USER: root
          PROXY_PASSWORD: ******
        ports:
          - 1080:1080
    

# Shadowsocks

:一种基于 SOCKS5 协议的代理协议,简称为 ss ,常用于实现 VPN 。

  • 官方文档 (opens new window)
  • 支持设置密码、加密传输数据。
  • 原理:
    1. 在一台主机上运行 ss 服务器。
    2. 在本机运行 ss 客户端,将本机的流量发送到 ss 服务器,被它代理转发。
  • ShadowsocksR :简称为 SSR ,是 shadowsocks 的分叉项目。

# Shadowsocks-libev

:一个 ss 代理服务器,采用 C 语言开发。

  • 支持 AEAD Cipher 加密算法。
  • 支持 Obfs 混淆,可以将 ss 流量伪装成 http 流量。
  • 以 Docker 方式运行:
    docker run -d --name shadowsocks --network host shadowsocks/shadowsocks-libev ss-server -s 0.0.0.0 -p 3000 -k ****** -m aes-256-gcm
    
  • 服务器的命令:
    ss-server               # 启动服务器
            -c config.json  # 使用指定的配置文件
            -s 0.0.0.0      # 设置服务器监听的 IP
            -p 3000         # 设置服务器监听的端口
            -k ******       # 设置服务器的认证密码
            -m aes-256-gcm  # 设置服务器的加密方式
    

# 客户端

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": 3000,
        "local_address": "127.0.0.1",
        "local_port": 3000,
        "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:3000 .
    # 第一个字段为 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 之后的一种新的代理服务器。

  • 采用自身原创的 VMess 代理协议,也兼容 HTTP、Shadowsocks 等协议。

# 代理客户端

  • 有的程序不支持使用代理,有的程序只支持使用 HTTP 等简单的代理协议。因此建议安装一个专用的代理客户端,通过两种方式代理其它程序的流量:
    • 透明代理(Transparent proxy):
      • 拦截其它程序发出的流量,转发到代理服务器。其它程序不会感知到代理,不需要主动使用代理。
    • 转换代理协议:
      • 通过某种代理协议连接到代理服务器,再在本机监听一个采用 HTTP 等简单代理协议的端口,将该端口收到的流量转发到代理服务器。
      • 此时,具有代理功能的程序,一般都能通过该端口使用代理。但没有代理功能的程序,依然不能使用代理。

# 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 包,转发到某个代理服务器。支持通配符。
    • 支持用多个代理服务器组成代理链。
  • 用法:
    1. 安装 Proxifier 并启动。
    2. 添加代理服务器。
    3. 添加代理规则。
    4. 保持 Proxifier 运行,即可代理本机程序的流量。

# ProxyChains

:一个 Unix 系统的命令行工具,采用 C 语言开发,用作代理客户端。

  • GitHub (opens new window)
  • 支持透明代理。
    • 原理:
      1. 声明环境变量 LD_PRELOAD ,让程序在导入 DLL 库时,优先导入 libproxychains4.so 库。
      2. 在 libproxychains4.so 库中,重写关于 Socket 通信的函数,将程序发出的 TCP 流量转发到代理服务器。
    • 缺点:
      • 只能代理 TCP 流量,不支持 UDP、ICMP 。
      • 只能代理指定的程序,不能代理系统所有进程。
      • 只能代理采用动态链接库的程序。
        • Chrome 浏览器在沙盒中运行网页,也不会被代理。

用法:

  1. 安装:
    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
    
  2. 编辑配置文件 /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  ******
    
  3. 执行命令:
    proxychains4 curl cip.cc  # 在代理下执行一条命令
    proxychains4 bash         # 创建一个 shell ,在其中执行的命令都采用代理
    

# redsocks

:一个 Linux 系统的命令行工具,采用 C 语言开发,用作代理客户端。

  • GitHub (opens new window)
  • 支持透明代理。
    • 原理:
      1. redsocks 连接到代理服务器,并在本机监听一个端口,将该端口收到的流量转发到代理服务器。
      2. 用户手动配置 iptables 防火墙规则,将本机发出的 TCP 流量重定向到 redsocks 端口。
    • 缺点:
      • 需要手动配置 iptables 规则,比较麻烦。
      • 有些程序可能无视 iptables 规则。

用法:

  1. 用 apt 安装:
    apt install redsocks
    
    或者手动编译后安装:
    git clone https://github.com/darkk/redsocks
    cd redsocks
    make
    cp redsocks /usr/bin/redsocks
    
  2. 编辑配置文件 /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{} 代理配置。
  3. 用 systemctl 保持运行:
    systemctl restart redsocks
    systemctl enable  redsocks
    
    或者手动启动:
    redsocks -c /etc/redsocks.conf
    
  4. 添加 iptables 规则:
    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 规则
    
    系统重启时会重置 iptables 规则。因此建议将配置 iptables 的命令保存为一个 shell 脚本,每次系统重启时执行它。

# Clash

:一个通用的代理客户端,采用 Golang 开发。

  • GitHub (opens new window)
  • 支持 HTTP、SOCKS、Shadowsocks、Vmess 等多种代理协议。
  • 支持 Linux、MacOS、Windows、Android 系统。
  • 在 Linux 系统上支持透明代理。
    • 原理与 redsocks 类似,需要手动配置 iptables 规则。

# 反向代理

实现反向代理的常见工具:

  • LVS
  • F5
    • :一个通过硬件实现负载均衡的服务器,基于 BIG-IP 协议。
  • HAProxy
    • :一个反向代理服务器,可以实现第四层的 TCP 代理、第七层的 HTTP 代理。
  • Nginx
    • :一个反向代理服务器,可以实现第四层的 TCP 代理、第七层的 HTTP 代理。
  • frp

# LVS

:Linux 虚拟服务器(Linux Virtual Server),是 Linux 的一个内核模块,通过转发 TCP/UDP 数据包,实现第四层的反向代理。

  • LVS 工作在内核态,比 Nginx 等用户态代理的性能更高。
  • 原理:
    • 创建一些 IPVS(IP Virtual Server)作为负载均衡器。
      • 每个 IPVS 绑定一个 Virtual IP ,称为 VIP 。
      • 每个 IPVS 负责将将访问 VIP 的 TCP、UDP 流量反向代理到某些后端的 Real Server IP ,称为 RIP 。
    • 配置 iptables 规则,将访问 VIP 的流量交给 IPVS 处理。
  • 有多种反向代理模式:
    • NAT 模式
      • :转发请求报文给后端时进行 DNAT ,转发响应报文给客户端时进行 SNAT ,实现透明代理。
    • TUN 模式
      • :将客户端的请求报文通过 IP 隧道(Tunnel)转发给后端,而后端直接返回响应报文给客户端。
      • 比 NAT 模式的速度更快。
    • DR 模式
      • :通过改写请求报文的目标 MAC 地址,将它转发给后端。而后端直接返回响应报文给客户端。
      • 比 TUN 模式的速度更快,但需要后端有一个独立的网卡。
  • 支持多种负载均衡算法:
    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 算法
    

# frp

:一个命令行工具,提供了反向代理、内网穿透的功能。

  • GitHub (opens new window)
  • 采用 Golang 开发。
  • 支持 TCP、UDP、HTTP、HTTPS 等多种代理协议。
  • 采用 C/S 架构工作。
    • frps :服务器,部署在任一主机上,不需访问外部,只需被 frpc、用户访问。
      • frps 所在主机通常拥有一个固定的外网 IP ,供外网用户访问。
      • 用户向 frps 发送网络包时,会先被 frps 转发到 frpc ,再被 frpc 转发到内网服务。
    • frpc :客户端,部署在任一主机上,不需被外部访问,只需访问到 frps、内网服务。

例:

  1. 登录一台主机,下载 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
    
  2. 登录另一个主机,编辑配置文件 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
    
  3. 让用户访问 frps 的反向代理端口:

    curl 1.1.1.1:10080
    

# VPN

:虚拟私有网络(Virtual Private Network),指由公网上的几台主机组成一个虚拟的私有网络。

  • 常用于实现正向代理,比如通过公网连接到某个私网的网关,建立一条专用信道,从而访问该私网。

# 运营商线路

国内互联网接入全球互联网的主要网络线路:

  • 电信运营商:

    • 163 :骨干网,路由节点的 IP 以 202.97 开头。
      • 省级、出国、国际都走 163 线路,从不走 CN2 线路。
      • 供普通用户使用,QOS 很低,高峰期时每个人分到的境外带宽低于 10 Kbps ,丢包率超过 50% 。
    • CN2 :中国电信下一代骨干网(Chinatelecom Next Carrier Network ,CNCN),路由节点的 IP 以 59.43 开头,提供高 QOS 服务。
      • CN2 GT :较差的 CN2 服务,省级、出国为 163 线路,国际为 CN2 线路。
      • CN2 GIA :最好的 CN2 服务,省级、出国、国际都走 CN2 线路,从不走 163 线路。
      • 双向 CN2 线路:出国、回国流量都走 CN2 线路。
      • 单相 CN2 线路:一般是出国流量走 CN2 线路,回国流量走 163 线路,高峰期依然拥挤。
  • 联通运营商:

    • 169 :骨干网
  • 移动运营商:

    • CMNET :骨干网