SQUID + ICAP + SSL BUMP 修改https内容

问题描述 投票:0回答:0

我正在尝试插入 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

javascript squid icap
© www.soinside.com 2019 - 2024. All rights reserved.