我正在尝试插入 JS 以使用 ICAP 阻止弹出窗口/新标签。 我已经使用 squid 设置了 tproxy,它适用于 https 连接我可以看到 REQMOD 请求,但我没有看到 RESPMOD。我认为我的 ssl bumping 设置不正确。如果我尝试访问 HTTP 站点,我会收到 ICAP 错误,对于 https,它工作正常
这是我的 squid.conf
acl ads dstdom_regex "/home/pi/adblocker/blocked_domains.txt"
http_access deny ads
debug_options ALL,1 33,28,2,9
acl localnet src 0.0.0.1-0.255.255.255 # RFC 1122 "this" network (LAN)
acl localnet src 10.0.0.0/8 # RFC 1918 local private network (LAN)
acl localnet src 100.64.0.0/10 # RFC 6598 shared address space (CGN)
acl localnet src 169.254.0.0/16 # RFC 3927 link-local (directly plugged) machines
acl localnet src 172.16.0.0/12 # RFC 1918 local private network (LAN)
acl localnet src 192.168.1.0/24 # RFC 1918 local private network (LAN)
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 allow localnet
http_access deny CONNECT !SSL_ports
http_access allow localhost manager
include /etc/squid/conf.d/*
http_access allow localhost
http_port 3128
https_port 3128 ssl-bump intercept generate-host-certificates=on cert=/home/pi/adblocker/ssl_cert1.pem key=/home/pi/adblocker/ssl_key1.pem
sslcrtd_program /usr/lib/squid/security_file_certgen -s /var/lib/ssl_db -M 4MB
sslcrtd_children 8
ssl_bump bump all
icap_enable on
icap_send_client_ip on
icap_send_client_username on
icap_client_username_encode off
icap_client_username_header X-Client-Username
icap_preview_enable on
icap_preview_size 1024
icap_service service_req reqmod_precache bypass=1 icap://127.0.0.1:1344/reqmod
adaptation_access service_req allow all
icap_service service_resp respmod_precache bypass=0 icap://127.0.0.1:1344/respmod
adaptation_access service_resp allow all
acl intermediate_fetching transaction_initiator certificate-fetching
http_access allow intermediate_fetching
request_header_access Allow allow all
request_header_access Authorization allow all
request_header_access WWW-Authenticate allow all
request_header_access Proxy-Authorization allow all
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% 432
`
这里是我的 icap 服务器的例子
import socketserver
import datetime
import re
from lxml import html
class ICAPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = self.request.recv(1024).strip()
response = self.handle_request(data)
self.request.sendall(response)
def handle_request(self, data):
lines = data.decode('utf-8').split('\r\n')
request_line = lines[0].split(' ')
method = request_line[0]
print("Received data:", data)
if method == 'OPTIONS':
return self.options_response().encode('utf-8')
elif method == 'REQMOD':
return data
elif method == 'RESPMOD':
print("Calling the Respmod_response method")
return self.respmod_response(data)
else:
return self.other_response().encode('utf-8')
def respmod_response(self, data):
content_type, content = self.extract_content(data)
if "text/html" in content_type:
modified_content = self.inject_script(content)
print('modified content')
return self.update_content_length(data, modified_content)
else:
print(data)
return data
def extract_content(self, data):
headers, content = data.split(b'\r\n\r\n', 1)
content_type = self.get_content_type(headers.decode("utf-8"))
return content_type, content.decode("utf-8")
def inject_script(self, content):
script_to_inject = '''
<script>
//code here
</script>
'''
print("Ready to inject")
parsed_html = html.fromstring(content)
head_list = parsed_html.xpath('//head')
if not head_list:
head = html.Element("head")
parsed_html.insert(0, head)
print("injecting head")
else:
head = head_list[0]
head.insert(0, html.fromstring(script_to_inject))
print('Injecting JS')
return html.tostring(parsed_html, encoding='utf-8')
def update_content_length(self, data, content):
data_str = data.decode("utf-8")
headers, body = data_str.split("\r\n\r\n", 1)
new_content_length = len(content)
headers = headers.replace(f'Content-Length: {len(body)}', f'Content-Length: {new_content_length}')
modified_data = f"{headers}\r\n\r\n".encode("utf-8") + content
return modified_data
def get_content_type(self, headers):
for line in headers.split('\r\n'):
if line.lower().startswith("content-type:"):
return line.split(":", 1)[1].strip()
return ""
def options_response(self):
response = 'ICAP/1.0 200 OK\r\n'
response += 'Methods: REQMOD, RESPMOD\r\n'
response += 'Service: PyICAP Server 1.0\r\n'
response += 'ISTag: "1.0"\r\n'
response += 'Max-Connections: 100\r\n'
response += 'Options-TTL: 3600\r\n'
response += 'Allow: 204\r\n'
response += 'Preview: 1024\r\n'
response += 'Transfer-Preview: *\r\n'
response += 'Transfer-Ignore: jpg,jpeg,gif,png\r\n'
response += 'Transfer-Complete: *\r\n'
response += 'Connection: close\r\n'
response += '\r\n'
return response
def other_response(self):
response = 'ICAP/1.0 204 No Content\r\n'
response += 'Connection: close\r\n'
response += '\r\n'
return response
def run(server_class=socketserver.TCPServer, handler_class=ICAPRequestHandler, port=1344):
server_address = ('', port)
server = server_class(server_address, handler_class)
print(f'ICAP server running on port {port}')
server.serve_forever()
if __name__ == '__main__':
run()
我首先启动服务器 - python3 icap_server.py 然后我开始鱿鱼 - sudo squid -N -d 9
1679950580.602 37 192.168.1.178 TCP_MISS/500 435 GET ANY HTTP request here - HIER_DIRECT/2600:1901:0:38d7:: text/html