完美解决 WSL2+mitmproxy 无法连接的问题 / windows子系统的端口映射及其原理
1 问题描述
项目需要,需要抓一下发送自手机app的数据包做degub。同时需要转发到内网环境,所以需要做一个中间人转发。然而用wsl2,不能直接访问虚拟机的虚拟ip,所以只能考虑把数据包发送到windows下,再转发给wsl。
先说明,这个问题在wsl1中是不存在的,因为wsl1和windows共用了同一套端口,不会有port forwarding 的问题。
现在我的问题是:按照流程安装完毕后,一切均正常,只是手机端连接不上。在已经PC和手机端都已经安装证书的情况下,手机一直不通ping,甚至无法接入互联网。同时,在wsl上也看不到任何来自手机端的连接请求。如果你遇到了一样的问题,那么大概率是因为wsl2的端口映射导致的。
2 解决方案
解决这个问题需要建立一个从windows 到wsl2 的端口映射关系。这个过程一般分为两步
- 1, 使用cmd建立一个端口映射关系。为此,需要准备三个值:windows下的源端口、wsl虚拟机ip地址、wsl下的目标端口
以上三个量中,windows下的源端口自己设置(不要和已有的应用程序发生冲突),wsl虚拟机ip地址一般是之前在ip addr中看到的地址,wsl下的目标端口是mitmproxy监听的端口号(默认为8080)。明确这三个值后,执行指令:(listenport是windows下源端口,我这里是8001,connectaddress是wsl的虚拟地址)
(记得以管理员身份执行)
netsh interface portproxy add v4tov4 listenport=8001 listenaddress=0.0.0.0 connectport=8080 connectaddress=xxx.xxx.xxx.xxx
之后使用netsh interface portproxy show all
查看自己建立的端口映射。我这里是这样的
(如果想要删除的话,执行netsh interface portproxy delete v4tov4 listenport=8001 listenaddress=0.0.0.0
)
- 2, 设立windows 出站规则
如果这时还不行,那么大概率是windows防火墙挡住了这些访问的数据包。可以使用以下方法解决:
依次打开防火墙与网络保护-->高级设置-->入站规则。点击新建规则
这里第一步选择端口-->选择TCP-->点击特定本地端口,填入之前选择的windows源端口(我这里是8001)--点击第一个允许连接,之后一路继续就好了。一直到配置完成。之后同理,完成UDP协议的转发设置。
- 设置mitmweb
在经历之前的两步之后,正常情况下,已经可以在shell里面看到访问log了。此时手机连接后,也可以正常浏览一些网页,但是对一些app可能有时候仍旧存在连接问题。
这个时候,仍需要对mitmproxy做一些关于ssh的校验设置。
使用指令mitmweb -k
进行监听,并访问对应的网页,勾选Don't verify server certificates。不再对服务端证书进行验证。问题得解。
(题外话:有的人(比如我)这个位置可能无法勾选,并会在命令行中弹出一个错误log,这个时候需要到左边edit options再进行一步操作,手动勾选ssl_insecure。如图
)
最后,由于wsl的虚拟地址不是固定的,每次都重新设置端口映射的话可能会很麻烦,所以读者可以考虑设置一下启动时自动配置ip地址,我自己写了一个小脚本,可以在开机时自动设置端口映射至wsl下的虚拟ip地址。有需要的同学可以去我的github下载。
3 原因
其实出现的核心原因在于WSL2 的网络机制。如果在cmd中使用ipconfig查看,可以发现多了一项wsl2 虚拟地址。这一重大改变允许wsl拥有自己的一些底层网络功能,但是同时也让运行在wsl上的网络应用更难访问。引用一段官方文档上的介绍:
WSL 2 做了架构的巨大变更,使用了虚拟化技术,并仍在努力改进网络支持。由于 WSL 2 现在运行在虚拟机中,因此你从 Windows 访问 Linux 网络应用程序需要使用该 VM 的 IP 地址,反之亦然,你需要 Windows 主机的 IP 地址才能从 Linux 中访问 Windows 网络应用程序。
4 内容参考
https://docs.microsoft.com/zh-cn/windows/wsl/compare-versions#whats-new-in-wsl-2