Stunnel 加密 Squid 代理服务

加密代理功能的实现,越过封锁限制,访问被墙的国外站点,比如 Google、FaceBook。

用户访问配置了代理服务的浏览器(可使用扩展实现自动切换代理,代理服务即国内 stunnel 监听地址), 国内 stunnel 开启加密连接国外 stunnel 再连接国外 squid 真实代理服务器请求实际网站并返回数据, 如下架构图:

按照上述图,也就是需要两台服务器,不过可以简化,国内 stunnel 可以直接在用户个人笔记本 / 台式机 启动,因为 stunnel 程序支持 windows、macOS、Linux。

以下步骤适用于 CentOS/RHEL 7.x 系统,stunnel 版本 4.56

一、国外的服务器安装 squid 和 stunnel

1. 安装 Squid

yum -y install squid openssl openssl-devel

2. 生成证书

openssl genrsa -out key.pem 2048
openssl req -new -x509 -days 3650 -key key.pem -out cert.pem -subj "/C=CN/ST=HeNan/L=ZhengZhou/O=devops/OU=know/CN=devops.com"

# ls
cert.pem  key.pem

squid 配置文件中添加:

https_port 4430 cert=/path/to/cert.pem key=/path/to/key.pem       # SSL PATH

/etc/squid/squid.conf 我的全部配置信息,按需修改

acl localnet src 127.0.0.1/8
acl localnet src <stunnel_ip>


http_access allow localhost 
http_access allow localnet 
http_access deny all

# PORT AND SSL PATH, 提供个 stunnel 高匿隧道
https_port 4430 cert=/path/to/cert.pem key=/path/to/key.pem

# 定义 squid 的cache 存放路径、cache目录容量、一级缓存目录数量、二级缓存目录数量
cache_dir ufs /var/spool/squid 100 16 256
coredump_dir /var/spool/squid

# 设置squid磁盘缓存最大文件,超过4M的不保存在硬盘
maximum_object_size_in_memory 4 MB

fqdncache_size 1024
cache_mem 300 MB
max_open_disk_fds 0  
minimum_object_size 1 KB
maximum_object_size 20 MB 

cache_swap_low 90 0%时停止

# 目录使用量大于95%时,开始清理旧的
cache_swap_high 95
ipcache_size 2048 
ipcache_low 90
ipcache_high 95 
refresh_pattern . 0 20% 4320 override-expire override-lastmod reload-into-ims ignore-reload

# Add any of your own refresh_pattern entries above these.

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

# 高匿
request_header_access via deny all
request_header_access X-Forwarded-For deny all

3. 启动 squid

# 初始化检测,并启动
squid -z 
systemctl enabled squid && systemctl start squid

二、国内服务器安装 stunnel

1. 安装 stunnel

yum -y install stunnel

2. 修改配置文件

# vi /etc/stunnel/stunnel.conf  默认没有这个文件,手动创建,默认读取这个文件
client=yes

[sproxy]
accept  = 0.0.0.0:7071
connect = 国外服务器IP:4430

解释说明:

accept = 0.0.0.0:7071 即是用户要开放的端口,

connect = 国外服务器 IP:4430 squid 服务器地址

3. 启动 stunnel 服务

stunnel 
# 或者
stunnel /etc/stunnel/stunnel.conf

此时用户连接到国内服务器 7071 作为代理就可以访问一些被墙的网站。

在国内没有服务器,可以在本地安装的一个 Stunnel,用来加解密,所以没有国内服务也不要紧。

去 stunnel 官网下载一个 windows 版的客户端(也许被 qiang,这里是 5.55,可直接下载)

注意: 同步时间

最好同步下国外服务器的时间,并与国内保持一致时区,否则有可能 SSL 验证错误。

stunnel.pem 详细参数

;;; CAfile = /etc/stunnel/stunnel.pem
;;; socket = l:TCP_NODELAY=1
;;; socket = r:TCP_NODELAY=1

;;;chroot = /var/run/stunnel
pid = /tmp/stunnel.pid
;;; verify = 3

;;; CApath = certs
;;; CRLpath = crls
;;; CRLfile = crls.pem

;;; setuid = stunnel
;;; setgid = stunnel

client=yes
compression = zlib
;;; taskbar = no
;;; delay = no
;;; failover = rr
;;; failover = prio
;;; sslVersion = TLSv1
;;; fips=no

;;; debug = 7
;;; syslog = no
output = /etc/stunnel/stunnel.log

[sproxy]
accept = 34567
connect = 127.0.0.1:3128

三、Ansible 批量部署

[root@localhost squid]# tree
.
|-- hosts
|-- install.yml
`-- roles
    |-- squid
    |   |-- files
    |   |   |-- cert.pem
    |   |   `-- key.pem
    |   |-- handlers
    |   |   `-- main.yml
    |   |-- tasks
    |   |   `-- main.yml
    |   `-- templates
    |       `-- squid.conf.j2
    `-- stunnel
        |-- handlers
        |   `-- main.yml
        |-- tasks
        |   `-- main.yml
        `-- templates
            `-- stunnel.conf.j2

hosts 和 install.yml

[root@localhost squid]# more hosts install.yml 
::::::::::::::
hosts
::::::::::::::
[squid]
192.168.1.33


[stunnel]
192.168.1.33


[all:vars]
ansible_ssh_port=22
ansible_ssh_user=root
ansible_ssh_pass=1
squid_ssl_port=4430


::::::::::::::
install.yml
::::::::::::::
---
- name: 'Deployment to squid'
  gather_facts: false
  hosts: squid
  roles:
    - { role: 'squid', tags: "install_squid" }

- name: 'Deployment to stunnel'
  gather_facts: false
  hosts: stunnel
  roles:
    - { role: 'stunnel', tags: "install_stunnel" }

squid 相关配置

[root@localhost squid]# more roles/squid/handlers/main.yml roles/squid/tasks/main.yml roles/squid/templates/squid.conf.j2
::::::::::::::
roles/squid/handlers/main.yml
::::::::::::::
- name: restart squid
  systemd:
    name: squid
    state: restarted
    enabled: yes
::::::::::::::
roles/squid/tasks/main.yml
::::::::::::::
- name: "Install squid stunnel openssl openssl-devel"
  yum:
    name: "{{ item.line }}"
    state: installed
  with_items:
    - {line: 'squid'}
    - {line: 'openssl'}
    - {line: 'openssl-devel'}

- name: 'Copy Squid pem to remote'
  copy: 
    src: "{{ item.src }}"
    dest: "{{ item.dest }}"
  with_items:
    - {src: 'key.pem', dest: '/etc/squid/key.pem'}
    - {src: 'cert.pem', dest: '/etc/squid/cert.pem'}

- name: 'template squid conf to remote'
  template:
    src: "{{ item.src }}"
    dest: "{{ item.dest }}"
  with_items:
    - {src: "squid.conf.j2", dest: "/etc/squid/squid.conf"}
  notify:
   - restart squid

- name: 'Crontab for restart squid'
  cron:
    name: restartSquid
    state: present
    hour: '23'
    job: "sync && echo 3 >/proc/sys/vm/drop_caches && rm -f /var/log/squid/access.log ; systemctl restart squid"

- name: 'Crontab for check squid'
  cron:
    name: CheckSquid
    state: present
    minute: '*'
    job: 'sleep 5 &&  systemctl status squid || systemctl start squid'

- name: 'See Port'
  shell: 'ss -tnlp |grep squid'
  register: return_status

- debug: 
    # msg: '{{ return_status.stdout_lines }}'
    var: return_status.stdout_lines
  #when: return_status.rc != 0
::::::::::::::
roles/squid/templates/squid.conf.j2
::::::::::::::
acl localnet src 127.0.0.1/8
#acl localnet src {{ ansible_ssh_host }}

{% for host in groups['stunnel'] %}

acl localnet src {{ host }}

{% endfor %}




http_access allow localhost 
http_access allow localnet 
http_access deny all


# PORT AND SSL PATH, 提供个 stunnel 高匿隧道
https_port {{ squid_ssl_port }} cert=/etc/squid/cert.pem key=/etc/squid/key.pem

# 定义 squid 的cache 存放路径、cache目录容量、一级缓存目录数量、二级缓存目录数量
cache_dir ufs /var/spool/squid 100 16 256
coredump_dir /var/spool/squid


# 设置squid磁盘缓存最大文件,超过4
maximum_object_size_in_memory 4 MB

fqdncache_size 1024
cache_mem 300 MB
max_open_disk_fds 0  
minimum_object_size 1 KB
maximum_object_size 20 MB 

cache_swap_low 90 0%时停
# 目录使用量大于95%时,开始清理旧的
cache_swap_high 95
ipcache_size 2048 
ipcache_low 90
ipcache_high 95 
refresh_pattern . 0 20% 4320 override-expire override-lastmod reload-into-ims ignore-reload

# Add any of your own refresh_pattern entries above these.

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

# 高匿
request_header_access via deny all
request_header_access X-Forwarded-For deny all

stunnel相关配置

[root@localhost squid]# more roles/stunnel/handlers/main.yml roles/stunnel/tasks/main.yml roles/stunnel/templates/stunnel.conf.j2     
::::::::::::::
roles/stunnel/handlers/main.yml
::::::::::::::
- name: restart stunnel
  shell: "ps -ef |grep stunnel |grep -v grep  |awk '{print $2}' |xargs kill -9  || stunnel"
::::::::::::::
roles/stunnel/tasks/main.yml
::::::::::::::
- name: "Install stunnel"
  yum:
    name: "{{ item.line }}"
    state: installed
  with_items:
    - {line: 'stunnel'}



- name: 'Template stunnel conf to remote'
  template:
    src: "{{ item.src }}"
    dest: "{{ item.dest }}"
  with_items:
    - {src: "stunnel.conf.j2", dest: "/etc/stunnel/stunnel.conf"}
  notify:
   - restart stunnel


- name: 'See Port'
  shell: 'ss -tnlp |grep stunnel'
  register: return_status


- debug: var=return_status.stdout_lines
  when: return_status.rc == 0
::::::::::::::
roles/stunnel/templates/stunnel.conf.j2
::::::::::::::
client=yes

{% for host in groups['squid'] %}

[squid_{{ loop.index }}]
accept  = 882{{ loop.index }}
connect = {{ host }}:{{ squid_ssl_port }}


{% endfor %}

Last updated