Bu1'Blog

如果能控制粗鄙的狂喜,就不会有深入骨髓的悲伤。

0%

Squid增加验证功能使得移设备也可以使用

写了很久,越写坑越多…最后发现了一个别的方案~

0x01 在WIFI与APN接入点中直接新建HTTP代理

  • WIFI

    长按连接上WIFI,点击修改网络后,选择代理并填入相关信息即可,支持自动验证~

  • 移动流量

    选择移动数据,点击接入点名称(APN),新建APN即可,数据不知道怎么填可以先看下系统默认的APN接入点。新建的时候如果代理设置了密码记得勾选身份验证类型。

注:如果不是开放式代理以上两种方法均会导致阿里云盘、抖音等软件无法使用。通过实验发现是这些流量不会自带账号密码,所以直接被拒绝了。等待后续优化~

0x02 参考链接


以下为旧内容

通过mysql存储用户验证通过的ip,通过实际验证改方案不怎么靠谱,会无限循环验证请求ip。

0x01 安装宝塔

需要用到mysql本来想手工安装的,但是想了下还是用宝塔吧~省时省心。

CentOS一键安装

1
yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh

更换一下登录端口

1
echo '8881' > /www/server/panel/data/port.pl && /etc/init.d/bt restart

注:安装完后自动打开系统防火墙

1
2
#查看防火墙状态
systemctl status firewalld.service

查看是否放行端口

1
firewall-cmd --zone=public --query-port=8881/tcp

放行指定的端口

1
2
##--permanent永久生效,没有此参数重启后失效
firewall-cmd --zone=public --add-port=8881/tcp --permanent

重启防火墙

1
firewall-cmd --reload

0x02 安装Mysql

宝塔可视化安装,或者手动安装也行,安装完后新建数据库squid,用户名squid。自定义也行记得住就行~。

之后新建一个表sq_client_ip用来存储数据。

还需要三个字段:

  • id(设置为主键)
  • username
  • client_ip
  • add_time

这里我直接可视化安装了,所以就没有贴代码了。整体结构为:

image-20211209160417851

0x03 安装python

如果没有安装的话直接安装就好了

1
yum -y install python

如果没有自动安装pip的话可以手动安装

1
yum install python-pip -y

再安装一下python的mysqldb库

1
pip install MySQL-python

python2对应的模块是mysqldb, mysqldb不支持python3

python3对应的模块是pymysql

安装报错可以先升级下pip版本

1
2
3
4
# 指定pip源
pip install packagename -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
# 更新pip
pip install --upgrade pip

0x04 编写基本验证器

在文件夹/etc/squid里新建AuthPro.py文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/python
# coding=UTF-8
import sys
import MySQLdb
""""""
def matchpasswd(login,passwd):
#用户名和密码,用于验证输入的用户名和密码。
#你可以自定义验证通过的要求,验证通过,返回True,验证不通过返回False
if (login == '修改为你的用户名' and passwd == '修改为你的验证密码'):
return True
else:
return False
def write_client_ip_to_db(username,client_ip):
#数据库地址,数据库用户名,数据库密码,数据库名,数据库编码格式
db=MySQLdb.connect("localhost","squid","修改为你的密码","squid",charset='utf8')
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# 向sq_client_ip表中插入用户名和用户ip
sql = "INSERT INTO sq_client_ip(username, client_ip) VALUES ('%s', '%s')" % (username,client_ip)
try:
# 执行sql语句
cursor.execute(sql)
#Ok 后面的print语句可以向cache日志中输出提示。/var/log/squid/cache.log查看
print("执行sql语句")
# 提交到数据库执行
db.commit()
except:
#打印错误内容
info = sys.exc_info()
print( info[0], ":", info[1])
#发生错误时回滚
db.rollback()

# 关闭数据库连接
db.close()
return
while True:
# read a line from stdin
line = sys.stdin.readline()
line = line.strip()
#提取输入参数。
username,password,client_ip = line.split()
#判断密码是否匹配
if matchpasswd(username, password):
#输出ok表示验证通过
sys.stdout.write('OK\n 密码验证通过')
#将客户端ip添加至数据库ip白名单
write_client_ip_to_db(username,client_ip)

else:
sys.stdout.write('ERR\n 密码验证失败')
# Flush the output to stdout.
sys.stdout.flush()

0x05 编写外部ACL辅助器

在文件夹/etc/squid里新建AclHelper.py文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/usr/bin/python
# coding=UTF-8
import sys
import MySQLdb
"""当用户连接squid,传递用户客户端ip地址到外部辅助器,辅助器通过标准输入读取。辅助器查询数据库符合客户端ip的所有项,如果查询结果,显示客户ip在数据库中,则输出ok,否则输出ERR"""
def matchclientip(client_ip):
#数据库地址,数据库名,数据库密码,数据库用户名,数据库编码格式
db=MySQLdb.connect("localhost","squid","你的数据库密码","squid",charset='utf8')
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# SQL 插入语句
sql = "SELECT * FROM sq_client_ip WHERE client_ip = '%s'" % (client_ip)
try:
# 执行sql语句
cursor.execute(sql)
result = cursor.fetchone()
if result:
exist_ip = True
else:
exist_ip = False
except:
# 发生错误时回滚
db.rollback()
exist_ip = False

# 关闭数据库连接
db.close()
return exist_ip
while True:
# 从标准输入读取一行,“client_ip”
line = sys.stdin.readline()
#提取输入参数。squid,输入给辅助器的字符串是"0 xx.xx.xx.xx"格式
#利用split分割字符串,得到0和client_ip的list
client_ip = line.strip().split()[1]
#判断密码是否匹配
if matchclientip(client_ip):
#输出ok表示验证通过
sys.stdout.write('OK\n')
#print会将信息输出到/var/log/squid/cache.log中。
print("Acl辅助器验证成功")
else:
sys.stdout.write('ERR\n')
print("ACL辅助器验证失败")
# Flush the output to stdout.
sys.stdout.flush()

0x06 修改squid配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# http_port 设置监听端口,默认为3128
http_port 6666

#父squid配置,配合国外服务器server2使用
nonhierarchical_direct off
#转发请求通过stunnel至父squid
cache_peer localhost parent 3128 0 default
never_direct allow all

# access_log 设置access日志,daemon表示在后台将日志写入/var/log/squid/access.log文件,
# combined是一个预定义的logformat,也可以使用自定义的logformat
access_log daemon:/var/log/squid/access.log combined


# ACLs all, manager, localhost, and to_localhost are predefined.
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

# 拒绝所有非Safe_ports的请求
http_access deny !Safe_ports
# 拒绝所有非SSL_prots的CONNECT请求
http_access deny CONNECT !SSL_ports

# Only allow cachemgr access from localhost
http_access allow localhost manager
#http_access deny manager
# 允许来自本地的请求
http_access allow localhost

######################################
#定义一个外部ACL辅助器
#使用python解释器,negativettl表示验证错误时的缓存时间单位秒,concurrency表示最多接收的认证通过用户,ipv4必须,如果没有ipv4会报错。
external_acl_type MyAclHelper negative_ttl=1 concurrency=30 ipv4 %SRC /usr/bin/python /etc/squid/AclHelper.py
acl MyAcl external MyAclHelper
http_access allow MyAcl

#定义一个验证器
#指定python运行目录,和python程序的目录
auth_param basic program /usr/bin/python /etc/squid/AuthPro.py
#向python程序中输入key_extras变量客户端ip"%>a"
auth_param basic key_extras "%>a"
#允许多少个子程序
auth_param basic children 30
#输入框提示信息
auth_param basic realm 输入用户名和密码
#验证信息的缓存时长
auth_param basic credentialsttl 1 second
#用户名和密码是否区分大小写
auth_param basic casesensitive on
#强制用户验证
acl authenticated proxy_auth REQUIRED
http_access allow authenticated
################################################

# 拒绝所有请求,最后兜底的规则
http_access deny all

重启squid使之生效

1
2
3
squid -z
systemctl restart squid.service
systemctl status squid

错误处理

连接数据库时报错

image-20211210140217623

找一下这个文件位置

1
2
[root@Q1nghuan squid]# find / -name mysql.sock
/tmp/mysql.sock

我看网上的文章一般是/tmp/目录下没有但是/var/目录下有???

既然这个模块要用到这个文件就做个软链接过去

1
2
mkdir /var/lib/mysql/
ln -s /tmp/mysql.sock /var/lib/mysql/mysql.sock

再次测试连接

1
python testdb.py

image-20211210140528102

这里的testdb.py使用的是菜鸟教程的参考实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/python
# -*- coding: UTF-8 -*-

import MySQLdb

# 打开数据库连接
db = MySQLdb.connect("localhost", "testuser", "test123", "TESTDB", charset='utf8' )

# 使用cursor()方法获取操作游标
cursor = db.cursor()

# 使用execute方法执行SQL语句
cursor.execute("SELECT VERSION()")

# 使用 fetchone() 方法获取一条数据
data = cursor.fetchone()

print "Database version : %s " % data

# 关闭数据库连接
db.close()

0x07 参考