mitmproxy.net.server_spec 模块深度解析:ServerSpec 类型与 parse() 解析规则

mitmproxy.net.server_spec 模块深度解析:ServerSpec 类型与 parse() 解析规则 mitmproxy.net.server_spec 模块深度解析ServerSpec 类型与 parse() 解析规则【免费下载链接】mitmproxyAn interactive TLS-capable intercepting HTTP proxy for penetration testers and software developers.项目地址: https://gitcode.com/GitHub_Trending/mi/mitmproxymitmproxy.net.server_spec是 mitmproxy 中用于描述“上游代理或目标服务器”的基础模块。它定义了ServerSpec类型别名和唯一的对外函数parse()负责把形如https://example.com:443、example.org、[::1]:8080这样的服务器地址字符串解析为结构化的(scheme, (host, port))元组。读完本文你将掌握 ServerSpec 的完整取值范围、parse()的正则解析规则与默认端口逻辑以及它在upstream、reverse等代理模式中的实际调用链。1. 模块定位一个模块一个类型一个函数该模块的文档页位于 API 文档入口对应源码为 mitmproxy/net/server_spec.py。模块 docstring 开篇即点明其职责Server specs are used to describe an upstream proxy or server.模块只导出两样东西结构极其精简ServerSpec服务器地址的类型别名parse()把字符串解析为ServerSpec的函数带cache装饰器。理解这两个入口就理解了整个模块。2. ServerSpec 类型scheme 与 (host, port) 的元组组合源码中的类型定义如下见 mitmproxy/net/server_spec.py#L11-L14ServerSpec tuple[ Literal[http, https, http3, tls, dtls, tcp, udp, dns, quic], tuple[str, int], ]也就是说一个合法的ServerSpec是二元组位置内容约束第一项协议 scheme必须是http/https/http3/tls/dtls/tcp/udp/dns/quic九种之一第二项(host, port)元组host 为字符串支持 DNS 名、IPv4、IPv6port 为 0–65535 的整数例如parse(http://example.com, https)返回(http, (example.com, 80))。这个类型在代码库中有多处直接消费说明它是 mitmproxy 内部“服务器地址”的统一表示mitmproxy/connection.py#L293Server连接对象的via字段类型为server_spec.ServerSpec | None用于记录“经由哪个上游代理”mitmproxy/proxy/layers/http/init.py#L110HTTP 代理层的via字段同样使用该类型示例脚本 examples/contrib/change_upstream_proxy.py 直接from mitmproxy.net.server_spec import ServerSpec并在request钩子里改写flow.server_conn.via ServerSpec((http, address))来动态切换上游代理。3. parse() 函数签名、参数与异常parse()的签名与官方示例摘自 mitmproxy/net/server_spec.py#L29-L40 的 docstringcache def parse(server_spec: str, default_scheme: str) - ServerSpec: Parses a server mode specification, e.g.: - http://example.com/ - example.org - example.com:443 *Raises:* - ValueError, if the server specification is invalid. 要点说明参数server_spec待解析的地址字符串。scheme 可省略省略时使用default_schemeport 也可省略省略时使用该 scheme 的默认端口。参数default_scheme字符串当输入未带scheme://前缀时的兜底协议。调用方根据业务语义传入不同默认值后文第 5 节会看到upstream模式传http、reverse模式传https。返回值ServerSpec即(scheme, (host, port))。异常任何非法输入都抛出ValueError且错误信息能精确定位到具体出错阶段见第 6 节测试验证。cache装饰器相同输入直接返回缓存结果parse()在代理模式解析等路径上可被反复调用而无需重复正则匹配。4. 正则与校验解析规则逐层拆解4.1 匹配正则解析的核心是一条 VERBOSE 正则mitmproxy/net/server_spec.py#L16-L26server_spec_re re.compile( r ^ (?:(?Pscheme\w)://)? # scheme is optional (?Phost[^:/]|\[.\]) # hostname can be DNS name, IPv4, or IPv6 address. (?::(?Pport\d))? # port is optional /? # we allow a trailing backslash, but no path $ , re.VERBOSE, )逐段解读片段含义(?:(?Pscheme\w)://)?scheme 可选形如http://、tls://整个前缀可有可无(?Phost[^:/]|\[.\])host 是“不含:和/的字符串”或“方括号包裹的 IPv6”因此天然支持 DNS 名、IPv4 与带括号的 IPv6 字面量(?::(?Pport\d))?port 可选以:数字形式出现/?允许一个结尾斜杠如http://example.com/但不允许任何路径——带/path的输入会匹配失败4.2 三层校验正则命中之后parse()还做三层显式校验每层抛出信息不同的ValueErrorscheme 白名单mitmproxy/net/server_spec.py#L45-L60显式给出的 scheme 或default_scheme都必须属于九种合法值否则抛出Invalid server scheme: {scheme}。例如ftp://example.com会被拒绝。host 校验mitmproxy/net/server_spec.py#L62-L67若 host 以[开头并以]结尾先剥掉括号即[::1]解析为::1随后调用 mitmproxy/net/check.py 中的check.is_valid_host(host)。该函数接受合法的 DNS 标签字母、数字、-、_单标签不超过 63 字节、完整主机名总长不超过 255 字节符合 RFC 1035、以及可通过ipaddress解析的 IPv4/IPv6 地址非法输入抛出Invalid hostname: {host}。port 校验mitmproxy/net/server_spec.py#L69-L83显式端口直接取整未给端口时按下表查默认值查不到即tls/dtls/tcp/udp/quic……不是其中五个无默认端口的 scheme就抛出Port specification missing最后用check.is_valid_port确认0 port 65535越界抛出Invalid port: {port}。4.3 scheme 默认端口表源码中的默认端口映射mitmproxy/net/server_spec.py#L73-L79scheme默认端口http80https443quic443http3443dns53tls/dtls/tcp/udp无默认端口必须显式指定 port这是一个容易踩坑的细节tcp、udp、tls、dtls这类裸传输层协议没有公认默认端口所以parse(example.com, tcp)会直接抛出Port specification missing而parse(smtp.example.com:25, tcp)才能成功得到(tcp, (smtp.example.com, 25))。5. 调用链parse() 在代理模式解析中的位置parse()最主要的生产调用方是代理模式解析模块 mitmproxy/proxy/mode_specs.py。该模块负责解析--mode参数其通用语法为mode [: mode_configuration] [ [listen_addr:]listen_port]例如reverse:https://example.com127.0.0.1:443表示在 localhost 的 443 端口上启动一个反向代理。模式名之后的mode_configuration部分正是server_spec.parse()的输入。两个关键子类UpstreamModemitmproxy/proxy/mode_specs.py#L207-L220对应--mode upstream:http://proxy:8080。它调用server_spec.parse(self.data, default_schemehttp)随后强制要求 scheme 只能是http或https否则抛出invalid upstream proxy scheme——也就是说虽然parse()本身认识九种 scheme但 upstream 模式只接受其中两种。ReverseModemitmproxy/proxy/mode_specs.py#L223-L246对应--mode reverse:https://target。它调用server_spec.parse(self.data, default_schemehttps)接受全部九种 scheme并根据解析结果决定监听协议http3/dtls/udp/quic走 UDPdns/https同时监听 TCP 与 UDP其余走 TCPdns的默认监听端口还会被覆写为 53。从源码结构看parse()的default_scheme参数设计正是为了这种“同一段字符串在不同模式下语义不同”的场景example.com作为 upstream 数据解释为http://example.com:80作为 reverse 数据解释为https://example.com:443。另一个实际使用场景是 examples/contrib/upstream_pac.py 脚本它在运行时把 PAC 脚本选出的代理 URL 送入server_spec.parse(proxy_url, http)动态决定每条流量走哪个上游代理ctx.options.direct_upstream_proxy也经由同一函数解析。6. 测试用例验证合法输入与四类错误单元测试 test/mitmproxy/net/test_server_spec.py 用参数化方式覆盖了合法路径与全部错误分支是最好的行为规格说明。6.1 合法输入行为输入 specdefault_scheme解析结果example.comhttps(https, (example.com, 443))http://example.comhttps(http, (example.com, 80))smtp.example.com:25tcp(tcp, (smtp.example.com, 25))http://127.0.0.1https(http, (127.0.0.1, 80))http://[::1]https(http, (::1, 80))http://[::1]/https(http, (::1, 80))结尾斜杠被允许https://[::1]/https(https, (::1, 443))http://[::1]:8080https(http, (::1, 8080))可以看到IPv6 字面量必须用方括号包裹否则冒号会与端口语法冲突解析结果中括号被剥离。6.2 错误分支均抛 ValueError输入异常信息触发阶段:Invalid server specification正则整体不匹配ftp://example.comInvalid server schemescheme 白名单校验$$$Invalid hostnamecheck.is_valid_host校验example.com:999999Invalid port端口范围校验example.comdefault_schemetcpPort specification missing该 scheme 无默认端口7. 小结与使用建议mitmproxy.net.server_spec虽然只有 85 行左右源码却是 mitmproxy 所有“指向某台服务器”配置的公共入口--mode upstream:、--mode reverse:的目标地址、connection.via上游记录、PAC 动态代理选择最终都收敛到同一个parse()函数。使用或扩展该模块时记住三条规则即可输入形如[scheme://]host[:port][/]路径部分不被接受scheme 缺省时由调用方决定默认协议upstream 为httpreverse 为httpstls/dtls/tcp/udp没有默认端口必须显式写 port否则解析失败。如需进一步深入可继续阅读 mitmproxy/proxy/mode_specs.py 中各ProxyMode子类的校验逻辑以及 test/mitmproxy/proxy/test_mode_specs.py 中对整体模式语法的测试。【免费下载链接】mitmproxyAn interactive TLS-capable intercepting HTTP proxy for penetration testers and software developers.项目地址: https://gitcode.com/GitHub_Trending/mi/mitmproxy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考