WSL起个服务,localhost访问嘛报错 connect ECONNREFUSED
开始以为是apipost的问题,postman也好浏览器也好都能访问,然后就apipost不行。
这边的同学用远程协助之后,我观察到apipost的log里面,localhost解析出来是127.0.0.1,但是我自己去控制台ping,解析出来是[::1] (win vista之后的默认)。
侧面说明了这127.0.0.1不是解析出来的,是代码里面写死的(code review?)。
这个么好办了,既然解析出来的 loopback address是IPV6的,那么我们直接用。
浏览器访问没问题,怀着高兴的心情去用,搞笑的是apipost不支持V6的地址,直接给我parse成http字符了。
好了只能另寻出路,查啊查,研究了一下WSL的网络(搞了n年linux现在来研究windows。。。),发现这货不是绑定到localhost的。
WSL2的虚拟机自己有个虚拟的NIC,你可以理解为localhost作为一个NAT网关,直接转发到下面设置好端口转发的wsl虚拟网卡上面。
想研究深入的自己看文档:https://docs.microsoft.com/en-us/windows/wsl/
这样么挺好,我们找到wsl自己的ip就好了,进wsl
~ ip -4 addr show eth0
5: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
inet 172.17.118.219/20 brd 172.17.127.255 scope global eth0
valid_lft forever preferred_lft forever
这样这个东西 172.17.118.219, 就是wsl的ip,这个可以直接放到apipost的环境里面去用,没有任何问题。
问题解决。
但是呢,wsl这东西每次启动都会换ip,很烦,怎么办,写个powershell脚本,等每次wsl启动完了跑一下,把这ip写到一个固定的host上面就好了 (所谓本地DDNS)
$hostname = "wsl"
# find ip of eth0
$ifconfig = (wsl -- ip -4 addr show eth0)
$ipPattern = "((\d+\.?){4})"
$ip = ([regex]"inet $ipPattern").Match($ifconfig).Groups[1].Value
if (-not $ip) {
exit
}
Write-Host $ip
$hostsPath = "$env:windir/system32/drivers/etc/hosts"
$hosts = (Get-Content -Path $hostsPath -Raw -ErrorAction Ignore)
if ($null -eq $hosts) {
$hosts = ""
}
$hosts = $hosts.Trim()
# update or add wsl ip
$find = "$ipPattern\s+$hostname"
$entry = "$ip $hostname"
if ($hosts -match $find) {
$hosts = $hosts -replace $find, $entry
}
else {
$hosts = "$hosts`n$entry".Trim()
}
try {
$temp = "$hostsPath.new"
New-Item -Path $temp -ItemType File -Force | Out-Null
Set-Content -Path $temp $hosts
Move-Item -Path $temp -Destination $hostsPath -Force
}
catch {
Write-Error "cannot update wsl ip"
}
脚本抄来的,写得很不错没必要自己改,原文在这里:https://abdus.dev/posts/fixing-wsl2-localhost-access-issue/,设置自动trigger这些都有。
本来想发到apipost自己论坛去的,给我报什么非法字符,也是无奈啊