Squid的模式

Squid作为高性能的代理服务,有以下模式:

  1. 传统正向代理 (Forward Proxy)

    1. CONNECT模式:

      • 当你的浏览器需要通过代理访问一个普通的 HTTP 网站时,它会发送一个 GET http://example.com/ 请求给代理服务器。代理服务器可以看到请求的完整URL(example.com)和内容,然后代表你去获取数据,并可以对其进行缓存和过滤。

      • 但当访问 HTTPS 网站(如 https://example.com)时,情况完全不同。HTTPS 的设计要求端到端加密,客户端(浏览器)和最终服务器(example.com)之间需要直接进行 TLS 握手,交换密钥,建立加密通道。任何中间人(包括代理服务器)如果试图解密内容,都会导致 TLS 握手失败(证书不匹配)。

    2. SSL_Bump模式:

      • Squid 主动窥探并解密 HTTPS 流量。它扮演一个“中间人”(MITM)的角色,分别与客户端和服务器建立独立的 SSL 连接,对流量进行解密的明文内容进行缓存、过滤、审计等操作。

  2. 反向代理 (Reverse Proxy) / Web 加速器

    类似Nginx;

  3. 透明代理 (Transparent Proxy)

    在防火墙或出口上重定向流量到Squid服务器进行代理,对于用户来说是透明的,无感知的;

使用HTTP模式代理HTTP或HTTPS流量

1、安装 Squid

通过 apt 包管理器安装 Squid,这是最简单的方法。

apt install squid

安装完成后,Squid 服务会自动启动。默认配置下,它只监听本地网络(localhost),我们需要修改配置来允许其他客户端连接。

2、配置 Squid

Squid 的主要配置文件是 /etc/squid/squid.conf,其中包含大量预定义配置,我们不需要,直接作为备份,新建配置文件。

mv /etc/squid/squid.conf /etc/squid/squid.conf.backup

然后使用文本编辑器(如 nanovim) 进行编辑:

vim /etc/squid/squid.conf

定义访问控制列表(ACL)

找到或创建 ACL 规则来定义允许访问代理的客户端 IP 地址或网络。

ACL可用元素

src:源地址(即客户机IP地址)

dst:目标地址(即服务器IP地址)

srcdomain:源名称(即客户机名称)

dstdomain:目标名称(即服务器名称)

time:一天中的时刻和一周内的一天

url_regex:URL规则表达式匹配

urlpath_regex:URL-path规则表达式匹配,略去协议和主机名

proxy_auth:通过外部程序进行用户验证

maxconn:单一IP的最大连接数

添加你的内部网络或特定 IP。例如,允许整个 192.168.1.0/24 网段和 10.0.0.0/24 网段:

# 在 acl 部分添加以下行
acl my_localnet src 192.168.1.0/24
acl my_localnet src 10.0.0.0/24

如果你想允许所有IP(不安全,仅用于测试),可以添加:

acl all_net src all

允许代理的流量

这是支持 HTTPS 流量的核心配置。

  1. 首先,定义你需要代理的服务

    acl http_ports port 80          # http
    acl SSL_ports port 443			# https
    acl ftp_ports port 21           # ftp
  2. 你需要允许你的客户端使用 CONNECT 方法连接到 443 端口。将默认的拒绝规则修改为只允许到安全端口。

    http_access allow my_localnet SSL_ports							# 修改为:允许代理 my_localnet 客户的 SSL_ports (443)的流量
  3. 如果你希望客户端的所有流量都可以被代理可以将上面的忽略,然后写入

    http_access allow all_net

(客户端访问未被允许的http流量)

image

配置HTTP和HTTPS代理监听端口以及允许进行代理客户端IP

http_access 部分,添加规则允许你的客户端网络访问。

http_port 8888							# 监听所有网络接口的 3128 端口,修改为监听8888
http_access allow my_localnet
# http_access allow all_net 			# 如果允许所有客户端

所有配置

acl all_net src all
http_access allow all_net
http_port 8888
access_log /var/log/squid/access.log
icp_port 0
htcp_port 0

3、验证配置并重启 Squid

在重启服务之前,务必检查配置文件语法是否正确。

sudo squid -k parse

如果输出中全是Processing,没有error证明配置没有问题

确认无误后,重启 Squid 服务以使配置生效:

sudo systemctl restart squid
sudo systemctl enable squid

你可以检查服务状态以确保它正常运行:

sudo systemctl status squid

4、配置防火墙(如果启用)

如果你的 Ubuntu 服务器启用了防火墙(如 UFW),你需要开放 Squid 监听的端口(例如 8888),这里写出nftables的配置

table inet inet_filter {
	chain input {
		ip protocol tcp tcp dport 8888 accept
	}
}

5、客户端测试

Linux/macOS 终端测试:

curl -x http://xxxxx:8888 https://baidu.com

浏览器测试:

在系统设置或浏览器的网络设置中,手动配置代理:

  • 代理类型: HTTP (对于 CONNECT 方法,浏览器会自动处理)

  • 地址: 你的服务器的 IP

  • 端口: 8888

如果你使用的是Edge或Google浏览器,无法在浏览器内配置代理,可用安装名为代理助手的浏览器插件,安装完成后右键,选择选项,填写http代理的服务器地址和端口后关闭,左键扩展图标,点击http代理即可。

然后访问一个 HTTPS 网站(如 https://baidu.com),看是否能正常打开。但此时,由于HTTP模式的代理属于明文,如果使用这种模式代理国外站点,会被GFW拦截,如果希望代理国外站点就需要配置HTTPS模式的代理。

image

使用HTTPS模式代理HTTP或HTTPS流量

正如上面所说,由于HTTP模式的代理属于明文,如果使用这种模式代理国外站点,会被GFW拦截,如果希望代理国外站点就需要配置HTTPS模式的代理。

1、安装squid的ssl扩展

apt install squid-openssl -y

2、申请证书

这一步可以申请域名的证书,也可以手动生成证书,但是手动生成的证书在使用时还需要在客户端导入CA证书,比较麻烦,因此这里直接使用已经申请好的证书。关于如何申请不在这里说明,可以使用Let`s Encrypt进行申请,但前提需要一个域名;

申请好的证书和私钥文件还需要进行以下配置,使其合二为一

cat server.key > server.pem
cat server.crt >> server.pem
mkdir /etc/squid/ssl
mv server.pem /etc/squid/ssl

3、修改squid的配置文件

添加证书相关内容

https_port 8443 cert=/etc/squid/ssl/squid.pem			# 指定https模式的端口和证书路径

Bump“窥探”模式(可选)

在某些场景下,例如:公司因需要进行海外业务,需要搭建一个方便内部员工访问海外站点的squid代理服务器,但为了安全,需要对员工访问海外站点的流量进行审计。可以选择“窥探”HTTPS流量。

原理是:Squid 主动窥探并解密 HTTPS 流量。它扮演一个“中间人”(MITM)的角色,分别与客户端和服务器建立独立的 SSL 连接,对流量进行解密的明文内容进行缓存、过滤、审计等操作。

比较复杂,暂不研究

所有配置

acl all_net src all
http_access allow all_net
http_port 8888
https_port 8443 cert=/etc/squid/server.pem
access_log daemon:/var/log/squid/access.log
icp_port 0
htcp_port 0

4、验证配置并重启 Squid

在重启服务之前,务必检查配置文件语法是否正确。

sudo squid -k parse

如果输出中全是Processing,没有error证明配置没有问题

确认无误后,重启 Squid 服务以使配置生效:

sudo systemctl restart squid
sudo systemctl enable squid

你可以检查服务状态以确保它正常运行:

sudo systemctl status squid

5、配置防火墙(如果启用)

如果你的 Ubuntu 服务器启用了防火墙(如 UFW),你需要开放 Squid 监听的端口(例如 8443),这里写出nftables的配置

table inet inet_filter {
	chain input {
		ip protocol tcp tcp dport { 8443, 8888} accept
	}
}

6、客户端测试

Linux/macOS 终端测试:

curl -x https://xxx.xxxx.xx:8443 https://baidu.com

浏览器测试:

在系统设置或浏览器的网络设置中,手动配置代理:

  • 代理类型: HTTP S(对于 CONNECT 方法,浏览器会自动处理)

  • 地址: 你的服务器的域名

  • 端口: 8443

如果你使用的是Edge或Google浏览器,无法在浏览器内配置代理,可用安装名为代理助手的浏览器插件,安装完成后右键,选择选项,填写http代理的服务器地址和端口后关闭,左键扩展图标,点击http代理即可。

这里要注意:如果是申请的证书的话,目的服务器一定需要使用域名进行配置,否则证书不会生效,因为生产环境中的证书一般都是匹配域名的,不能匹配IP地址!

image

高级配置与安全提示

身份验证:上述配置仅基于 IP 地址进行控制。为了更安全,你应该添加用户名密码认证。

apt install apache2-utils					# 安装 apache2-utils 来创建密码文件
htpasswd -c /etc/squid/passwd xxxx			# 创建密码文件并添加用户 'xxxx',输入两次密码
htpasswd /etc/squid/passwd xxxx				# 追加用户,不能使用-c,要不然会覆盖原来的文件

squid.conf 中添加:

auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwd
auth_param basic realm proxy
acl authenticated proxy_auth REQUIRED
# http_access allow all_net						# 禁用之前配置的允许所有网络使用代理
http_access allow authenticated					# 只有通过验证的用户才可以使用代理

所有配置

auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwd		# 指定
acl auth_user proxy_auth REQUIRED												# 定于认证用户

auth_param basic children 5														# 认证子进程数量5
auth_param basic realm Squid Proxy Server										# 指定认证领域(显示在登录对话框中的描述)
auth_param basic credentialsttl 2 hours											# 认证凭据的有效期
auth_param basic casesensitive on												# 是否对用户名大小写敏感

http_access allow auth_user														# 认证成功的用户允许代理所有流量
http_access deny all															# 其余用户拒绝代理所有流量
http_port 8888
https_port 8443 cert=/etc/squid/server.pem
access_log daemon:/var/log/squid/access.log
icp_port 0
htcp_port 0

image

或者直接在设置HTTPS代理的时候就写上认证信息

image

代理自动配置(PAC)

代理自动配置(PAC) 文件是一个 JavaScript 函数,用于确定 web 浏览器请求(HTTP、HTTPS 和 FTP)是直接连接到目的地还是转发到 web 代理服务器。PAC 文件中包含的 JavaScript 函数定义了该函数:

自动配置文件应保存为扩展名为 .pac 的文件:proxy.pac。其 MIME 类型需要设置为 application/x-ns-proxy-autoconfig

该文件包含一个名为 FindProxyForURL 的函数。下面的示例将在内部 DNS 服务器设置为只能解析内部主机名的环境中运行,目标是只对无法解析的主机使用代理:

function FindProxyForURL(url, host) {
  if (isResolvable(host)) {
    return "HTTPS proxy.mydomain.com:8080";
  }
  return "DIRECT";
}

参见https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Guides/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_PAC_file以获取更多示例。