Squid 服务

代理服务器

代理服务器(Proxy Server)是以类似代理人的身份去获取用户所需数据。通过代理服务器可以实现防火墙与用户浏览数据分析功能。此外,还能充当 CDN(Content Delivery Network),即内容分发网络功能,加速网络访问。

一般代理服务器会搭建在局域网的单点对外防火墙上。

Linux 下常用的代理服务使用 Squid 软件。

配置文件

先使用 yum 安装 squid 服务:

[root@server2 ~]$ yum install -y squid

squid 服务使用的配置文件有:

  • /etc/squid/squid.confsquid 的主要配置文件。
  • /etc/squid/mime.conf:设置 squid 所支持的文件格式,一般不需要改动。

squid 服务相关目录有:

  • /var/spool/squid:默认 squid 缓存储存目录。
  • /usr/lib64/squid:提供 squid 额外的控制模块。

默认配置

在默认情况下,squid 配置有下面一些设置:

  • 仅有本机(localhost,127.0.0.1)来源可以使用 squid 功能。
  • squid 所监听的代理服务端口为 3128。
  • 缓存目录 /var/spool/squid/ 仅有 100 MB 缓存量。
  • 内存分配 8 MB 大小作为高速缓存使用。
  • 启动 squid 程序的用户为 squid 账号。

默认配置文件内容如下:

[root@server2 ~]$ cat /etc/squid/squid.conf
# 信任用户与目标控制
acl localnet src 10.0.0.0/8     
acl localnet src 172.16.0.0/12  
acl localnet src 192.168.0.0/16 # 定义局域网来源
acl localnet src fc00::/7       # RFC 4193 local private network range
acl localnet src fe80::/10      # RFC 4291 link-local (directly plugged) machines

# 定义安全端口
acl SSL_ports port 443
acl Safe_ports port 80          # http
acl Safe_ports port 21          # ftp
acl Safe_ports port 443         # https
acl Safe_ports port 70          # gopher
acl Safe_ports port 210         # wais
acl Safe_ports port 1025-65535  # unregistered ports
acl Safe_ports port 280         # http-mgmt
acl Safe_ports port 488         # gss-http
acl Safe_ports port 591         # filemaker
acl Safe_ports port 777         # multiling http
acl CONNECT method CONNECT

# 拒绝非正规端口连接请求
http_access deny !Safe_ports

# 拒绝非正规加密端口连接请求
http_access deny CONNECT !SSL_ports

# 允许本机管理,拒绝其他来源地址管理
http_access allow localhost manager
http_access deny manager

# 放行本机与内部网络的用户来源,其他予以拒绝
http_access allow localnet
http_access allow localhost
http_access deny all

# 监听客户端请求的端口.如果想加密连接可改为https_port 923
http_port 3128

# 磁盘缓存放置目录与大小,内存高速缓存的大小
cache_dir ufs /var/spool/squid 100 16 256
cache_mem 8 MB

# Leave coredumps in the first cache dir
coredump_dir /var/spool/squid

# 额外设置
refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
refresh_pattern .               0       20%     4320

服务启动

可以使用默认配置启动 squid

[root@server2 ~]$ systemctl start squid
[root@server2 ~]$ netstat -ntulp |grep squid
tcp6       0      0 :::3128                 :::*             LISTEN      101226/(squid-1)
udp        0      0 0.0.0.0:56694           0.0.0.0:*                    101226/(squid-1)
udp6       0      0 :::53318                :::*                         101226/(squid-1) 

缓存目录

磁盘缓存设置 cache_dir ufs /var/spool/squid 100 16 256 后三数字代表:大小 MB、一层索引数、二层索引数。

[root@server2 ~]$ ls /var/spool/squid/
00  01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F  swap.state
[root@server2 ~]$ ls /var/spool/squid/00
00  0B  16  21  2C  37  42  4D  58  63  6E  79  84  8F  9A  A5  B0  BB  C6  D1  DC  E7  F2  FD

因为 squid 会将数据分成多个小块,这样便于索引。

可以多加一行配置来增加磁盘缓存目录。例如:cache_dir ufs /cache 2000 64 64。同时需要修改目录权限:

[root@server2 ~]$ mkdir /cache
[root@server2 ~]$ chmod 750 /cache
[root@server2 ~]$ chown squid:squid /cache
[root@server2 ~]$ chcon --reference /var/spool/squid/ /cache
[root@server2 ~]$ ll -Zd /cache
drwxr-x---. squid squid system_u:object_r:squid_cache_t:s0 /cache

为了防止缓存占满硬盘,可以在配置中设置下面两个值,当磁盘使用率达到 95% 时删除旧数据,直到磁盘用量降至 90%:

cache_swap_low 90
cache_swap_high 95

cache_mem 的值指额外提供给 squid 作为缓存使用的内存大小。默认 1 GB 磁盘高速缓存会占用约 10 M 内存。

信任来源

Squid 中来源与目标过滤使用 acl 来定义列表,用 http_access 来对 acl 采取动作。设置 acl 的语法为:

acl <自定义acl名称> <要控制acl类型> <设置内容>

重要的 acl 类型设置如下:

  • 设置请求客户端列表方式有下面几种:
    • src ip-address/netmask:通过 IP 设置网段,例如acl plan src 10.1.1.0/24 10.1.2.0/24
    • src addr1-addr2/netmask:连续 IP 地址设置,例如acl plan src 10.1.1.100-10.1.1.200/24
    • srcdomain .domain.name:通过主机名设置,例如acl pdo srcdomain .ere.edu.us
  • 设置访问目标列表方式有下面几种:
    • dst ip-addr/netmask:通过 IP 设置,例如acl drp dst 134.144.2.54/32
    • dstdomain .domain.name:通过域名设置,例如acl drp dstdomain .facebook.com
    • url_regex [-i] ^http://url:用正则表达式匹配网址,例如acl kurl url_regex ^http://baidu.com/.*
    • urlpath_regex [-i] \.gif\$:用正则匹配 url 内容,例如acl sx urlpath_regex /sex.*\.jpg$
    • 匹配文件:可以将地址按行保存到文件来调用,例如acl drplst dstdomain "/root/dpl.txt"

设置好 acl 后,可以用 http_access 来对 acl 列表执行允许(allow)与拒绝(deny)操作,http_access 严格按顺序执行。

例如放行内部网络 10.1.1.0/24,拒绝访问 facebook.com 网站的设置如下:

acl lanet src 10.1.1.0/24
acl drpdm dstdomain .facebook.com
http_access deny drpdm
http_access allow lanet

其他设置

可以设置不要对某些网页进行缓存操作,否则客户端无法请求到网页最新副本。例如,不要对 php 网页进行缓存:

acl denyphp urlpath_regex \.php$
cache deny denyphp

refresh_pattern 段设置,例如:refresh_pattern ^ftp: 1440 20% 10080。从第二列开始代表:

  • regex:用正则表达式分析网址数据,例如 ^ftp 表示以 ftp 开头的网址。
  • 最小时间:单位分钟,表示缓存数据存放到达这一时间后失效,新请求会从网络重新获取数据。
  • 百分比:与最大时间有关,当数据被获取到缓存后,经过最大时间的百分比后,数据会被重新获取。
  • 最大时间:数据存在缓存内的最大时间,到达这一时间后数据会被删除。

管理员的邮箱地址可以通过 cache_mgr 来设置,在发生错误时会发送邮件。例如设置邮箱为 root@server2

cache_mgr root@server2
visible_hostname server2

安全设置

针对防火墙,需要开放 3128 端口:

[root@server2 ~]$ iptables -A INPUT -i ens37 -p tcp -s 10.1.1.0/24 --dport 3128 -j ACCEPT

SELinux 中没有规则限制,其中 /etc/squid/ 内配置文件类型是 squid_conf_t,缓存目录类型 squid_cache_t

通过将拒绝网站写入文件中调用处理起来更灵活。例如使用 /root/drp.txt 来记录禁止网站:

[root@server2 ~]$ vi /root/drp.txt
.facebook.com
.google.com
[root@server2 ~]$ vi /etc/squid/squid.conf
acl drplist dstdomain "/root/drp.txt"
http_access deny drplist
[root@server2 ~]$ systemctl reload squid

客户端测试

这里使用 curl 来测试。默认情况下可以访问百度:

[root@server3 ~]$ curl baidu.com
<html>
<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
</html>

squid 中添加规则后重新载入配置:

[root@server2 ~]$ vi /etc/squid/squid.conf
acl nobaidu dstdomain .baidu.com
http_access deny nobaidu
[root@server2 ~]$ systemctl reload squid

再用 curl 通过代理访问百度:

[root@server3 ~]$ curl -x 10.1.1.1:3128 baidu.com
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<meta type="copyright" content="Copyright (C) 1996-2016 The Squid Software Foundation and contributors">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>ERROR: The requested URL could not be retrieved</title>

出现 squid 页面提示禁止访问。

上层代理

可以在 squid 中设置上层代理,来将网络访问分流。设置上层代理服务器参数如下:

  • cache_peer

    用法:cache_peer [上层代理主机] [代理角色] [代理端口] [icp端口] [额外参数]

    • 上层代理主机名:例如 192.168.1.101。

    • 代理角色:角色一般为上层(parent)。还有临近(sibling)协同运行角色。

    • 代理端口:上层代理的端口,默认是 3128。

    • icp 端口:默认是 3130。

    • 额外参数: 针对上层代理的行为设置,主要选项有:

      • proxy-only:数据不缓存到本地。
      • weight:权重设置,有多台上层代理时用更高权重表示优先选择。
      • no-query:可以不需要发送 icp 数据包。
      • no-digest:不向附近主机要求建立 digest 记录表格。
      • no-netdb-exchange:不向附近代理主机发送 IMCP 数据包。
  • cache_peer_domain

    用法:cache_peer_domain [上层代理主机名] [请求的域名]

    设置请求用上层代理服务器访问的域名。

  • cache_peer_access

    用法:cache_peer_access [上层代理主机名] [allow|deny] [acl名称]

    cache_peer_domain 作用类似,不过用 acl 来规范访问行为。

例如设置使用代理 DESKTOP-QU8VM21:3213 去访问谷歌:

[root@server2 ~]$ vi /etc/squid/squid.conf
cache_peer DESKTOP-QU8VM21 parent 3213 3130 proxy-only
cache_peer_domain DESKTOP-QU8VM21 .google.com
[root@server2 ~]$ systemctl reload squid

透明代理

可以在对外防火墙服务器 nat 上安装代理,在代理上启动 transparent 功能,最后加上 80 端口转 3128 端口的规则,那么所有通过 nat 转发的内网主机上网都会强制通过代理访问 http。客户端的浏览器也不需要做任何额外设置。

开启透明代理功能只需要在 http_port 3128 后面加上 transparent 参数即可:

[root@server2 ~]$ vi /etc/squid/squid.conf
http_port 3128 transparent
[root@server2 ~]$ systemctl reload squid

接着增加一条防火墙转发规则:

[root@server2 ~]$ iptables -t nat -A PREROUTING -i ens37 -s 10.1.1.0/24 -p tcp --dport 80 -j REDIRECT --to-ports 3128

至此便完成了。

代理认证

squid 使用 ncsa_auth 认证模块,可以配合 apache 提供的 htpasswd 制作的密码文件作为验证依据,来对代理使用进行身份认证:

[root@server2 ~]$ rpm -ql squid | grep ncsa
/usr/lib64/squid/basic_ncsa_auth
[root@server2 ~]$ yum install -y httpd
[root@server2 ~]$ whereis htpasswd
htpasswd: /usr/bin/htpasswd

设置 squid.conf 内容,账号密码保存在 /root/squid_user.txt

[root@server2 ~]$ vi /etc/squid/squid.conf
auth_param basic program /usr/lib64/squid/basic_ncsa_auth /root/squid_user.txt
auth_param basic children 5
#acl localnet src 10.0.0.0/8    # RFC1918 possible internal network
auth_param basic program /usr/lib64/squid/basic_ncsa_auth /root/squid_user.txt
auth_param basic children 5
acl squid_user proxy_auth REQUIRED
http_access allow squid_user

通过 htpasswd 建立用户 sqq,密码为 1234

[root@server2 ~]$ htpasswd -c /root/squid_user.txt sqq
New password: 
Re-type new password: 
Adding password for user sqq
[root@server2 ~]$ systemctl restart squid