公司的业务需要一点翻墙服务, 于是就在我的电脑上部署了clash for windows, 并且使用的是TUN模式, 俗称tunnel, 这个模式的官方解释是

对于不遵循系统代理的软件,TUN 模式可以接管其流量并交由 CFW 处理,在 Windows 中,TUN 模式性能比 TAP 模式好

这样一些例如conda, pip, ubuntu源等就不需要再额外配置了, 直接走的是策略组, 但是随着业务的增加, 我发现了一个最近很奇怪的现象.

因为这些都不是必须的, 所以就没怎么管, 偶然一次电脑没运行clash, 然后docker和tailscale竟然正常了! 我很好奇, 于是就在排查

  1. 首先手动运行Tailscale的service, 发现其存在:

    Received error: register request: Post "<https://controlplane.tailscale.com/machine/register>":
    connection attempts aborted by context: context deadline exceeded
    

    由此可见是连不上controlplane.tailscale.com的缘故, 同时使用nslookup [controlplane.tailscale.com](<http://controlplane.tailscale.com/>)发现其返回ip为

    nslookup controlpanel.tailscale.com
    服务器:  UnKnown
    Address:  198.18.0.2
    
    名称:    controlplane.tailscale.com
    Address:  198.18.0.129
    

    既然返回值为198.18.0.129, 有可能就是由clash的TUN模式的fake-ip所引发的, 于是我关闭TUN模式, 立刻就能登录了.

    (2023.11.14更新:在dns配置中fake-ip-filter添加 - "*.tailscale.com" )

    dns:
    	fake-ip-filter:
        - '*.lan'
        - '*.tailscale.com'
    

    也可以修改mixin配置:

    mixin:
      hosts:
        'controlplane.tailscale.com': '3.74.105.242' #自己使用下面的链接解析一下ip
    

    **https://site.ip138.com/controlplane.tailscale.com/**

    Untitled

  2. 有了上面的经验, 我就先关闭了TUN, 然后docker也就好了! 但一直开关TUN模式不是个事, 于是我就在查找日志, 发现日志中存在如下:

    [com.docker.backend.exe.httpproxy][I] HTTP 1091 GET <http://http.docker.internal:3128/:> with direct connection
    [com.docker.backend.exe.httpproxy][I] HTTP 1090 GET <http://http.docker.internal:3128/:> proxying to http.docker.internal:3128
    [com.docker.backend.exe.socketforward][I] error copying: read tcp 198.18.0.1:54036->198.18.0.128:3128: wsarecv: An existing connection was forcibly closed by the remote host.
    ......
    [com.docker.backend.exe.ipc][I] (c85381e1) 2b188200-idle C->S lifecycle GET /vm/ram-cpu-usage
    

结合日志, 上谷歌搜索, 才发现, Docker Desktop和Docker daemon通讯是靠com.docker.service, *com.docker.service 是一个Windows服务,它以 SYSTEM 特权在后台运行。它监听命名管道 //./pipe/dockerBackendV2 。Docker Desktop连接到命名管道并向服务发送命令。此命名管道受到保护,只有属于 docker-users 组的用户才能访问它。*

https://docs.docker.com/desktop/windows/permission-requirements/#privileged-helper

We recommend that you connect to the special DNS name host.docker.internal, which resolves to the internal IP address used by the host.

我们建议您连接到特殊的 DNS 名称 host.docker.internal ,该名称解析为主机使用的内部 IP 地址。

*https://docs.docker.com/desktop/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host*

Ensuring that host.docker.internal and gateway.docker.internal are defined in the Win32 hosts file. They point to the host local IP address and allow an application to resolve the host IP using the same name from either the host itself or a container.

确保在 Win32 主机文件中定义 host.docker.internal 和 gateway.docker.internal 。它们指向主机本地 IP 地址,并允许应用程序使用主机本身或容器中的相同名称来解析主机 IP。

https://docs.docker.com/desktop/windows/permission-requirements/#privileged-helper

即当*host.docker.internal* 解析的是我本机局域网地址, DockerDesktop才可以正常和服务发送命令.

运行nslookup host.docker.internal发现

nslookup host.docker.internal
服务器:  UnKnown
Address:  198.18.0.2

*** UnKnown 找不到 host.docker.internal: Non-existent domain

于是勾选 Add the *.docker.internal to hosts:

Untitled

然后查看本机hosts :

# Added by Docker Desktop
192.168.19.42 host.docker.internal
192.168.19.42 gateway.docker.internal
# To allow the same kube context to work on the host and the container:
127.0.0.1 kubernetes.docker.internal
# End of section

ipconfig /flushdns刷新本地DNS缓存后再次运行nslookup host.docker.internal发现依旧无法解析, 明明Docker Desktop已经做好准备工作, 但是无法解析. 于是我就再查, 发现是Clash默认劫持了本机的53端口的DNS请求, 导致hosts不生效, 于是Docker Desktop无法连接到host.docker.internal, 也就无法获取到启动状态, 解决方法是在Clash配置文件中配置某些域名返回指定的ip. 手动设置mixin:

mixin:
    hosts:
        'host.docker.internal': '192.168.19.42' #配置为你的局域网地址
        'http.docker.internal': '192.168.19.42' #配置为你的局域网地址
        'gateway.docker.internal': '192.168.19.42' #配置为你的局域网地址
        'kubernetes.docker.internal': '127.0.0.1' #配置为127.0.0.1