You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python拦截浏览器流量并实现重定向与目标主机名获取?

实现网络请求拦截与重定向(含主机名获取)

要实现类似虚拟局域网的请求拦截重定向,核心难点是准确获取目标主机名,不同网络层级的实现方式差异很大,以下是分场景的可行方案:

一、DNS劫持(最直接获取主机名)

这是获取目标主机名最可靠的方式——浏览器发起请求前会先做DNS解析,拦截这个阶段的请求可以直接拿到域名,同时直接返回指定IP实现重定向,无需处理后续数据包。

实现方式

  1. 本地DNS服务器:运行轻量DNS服务,将系统DNS设置指向本地,拦截特定域名的解析请求并返回目标IP,其他请求转发到公共DNS。
  2. 系统调用钩子:通过钩子劫持系统的DNS解析函数(如Windows的getaddrinfo、Linux的gethostbyname),直接修改解析结果。

代码示例(Python本地DNS服务器)

from dnslib import DNSRecord, RR, QTYPE, A
import socket

REDIRECT_MAP = {
    "example.com": "192.168.1.100",
    "test.example.org": "10.0.0.5"
}
DEFAULT_DNS = ("8.8.8.8", 53)

def handle_dns_query(data, addr, sock):
    req = DNSRecord.parse(data)
    qname = str(req.q.qname)[:-1]  # 去除域名末尾的点
    
    resp = req.reply()
    if qname in REDIRECT_MAP:
        # 返回指定IP
        resp.add_answer(RR(rname=req.q.qname, rdata=A(REDIRECT_MAP[qname]), ttl=300))
    else:
        # 转发到公共DNS
        forward_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        forward_sock.sendto(data, DEFAULT_DNS)
        forward_data, _ = forward_sock.recvfrom(1024)
        resp = DNSRecord.parse(forward_data)
    
    sock.sendto(resp.pack(), addr)

def run_dns_server():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind(("0.0.0.0", 53))
    print("DNS拦截服务启动: 0.0.0.0:53")
    while True:
        data, addr = sock.recvfrom(1024)
        handle_dns_query(data, addr, sock)

if __name__ == "__main__":
    run_dns_server()

二、应用层代理(HTTP/HTTPS请求拦截)

如果需要在请求发起后基于应用层信息(如路径、Header)判断,可使用应用层代理,直接获取HTTP的Host头或HTTPS的SNI字段(TLS握手时的服务器名称)识别目标主机名,再转发到指定IP。

实现方式

  1. 透明代理:通过系统工具(Linux的iptables、Windows的WinDivert)将流量转发到代理端口,代理解析请求后再转发。
  2. 显式代理:配置浏览器使用你的代理服务,直接处理所有请求。

关键注意事项

  • HTTPS请求需要生成自签名CA证书并导入系统信任,否则代理无法解密流量获取SNI或Host头。
  • 可借助现成框架(如Python的mitmproxy)快速实现,无需从零开发。

三、内核级数据包拦截(驱动级效果)

若需要接近驱动级的低延迟拦截,可在网络内核层处理数据包,但IP数据包本身不包含主机名,需结合以下方式:

  1. 先通过DNS劫持记录「域名-IP」映射表,再在内核层拦截对应IP的流量,修改目标地址。
  2. 对HTTPS流量,解析TLS握手包中的SNI字段(内核层解析TLS复杂度较高)。

实现方式

  • Linux:使用eBPF或netfilter内核模块,拦截IP数据包并修改目标IP。
  • Windows:使用WFP(Windows Filtering Platform)驱动或WinDivert(用户态但接近驱动级的工具)。

代码示例(Linux eBPF简化版)

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>

// 要重定向的原目标IP和新IP(网络字节序)
#define OLD_DST_IP 0x0a000001 // 10.0.0.1
#define NEW_DST_IP 0xc0a80164 // 192.168.1.100

SEC("tc")
int redirect_target_ip(struct __sk_buff *skb) {
    __be32 dst_ip = skb->dst_ip;
    
    if (dst_ip == OLD_DST_IP) {
        skb->dst_ip = NEW_DST_IP;
    }
    return TC_ACT_OK;
}

char _license[] SEC("license") = "GPL";

四、方案选择建议

  • 优先选DNS劫持:实现简单、性能高,能直接获取准确的主机名,适合大部分场景。
  • 若需处理直接访问IP的请求,或需要基于应用层信息判断,选应用层代理。
  • 若追求极致性能或系统级拦截效果,选内核级拦截+DNS映射的组合。

内容的提问来源于stack exchange,提问作者chronosirius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 23:55:21