写在前面:为何回归 NAT 模式?

WSL2 全新的 networkingMode=mirrored(镜像网络模式)在理论上提供了极大的便利,尤其是在 localhost 互通和局域网访问方面。然而,作为一项实验性功能,我在实践中遇到了许多难以排查的网络“坑”,尤其是在与 Docker 结合使用时,出现了连接被拒绝、代理不生效等一系列问题。

在花费大量时间排错后,我决定回归到 WSL2 久经考验的默认 NAT 模式。这种模式虽然需要一些手动配置,但其行为是可预测且极其稳定的。

本指南旨在为那些和我一样,选择从 mirrored 模式切换回 NAT 模式,或初次在 NAT 模式下配置代理的用户,提供一套完整、可靠的解决方案。本文将以在 Windows 主机上运行 Clash for Windows 代理程序为例,其默认端口为 7890

前置步骤:Windows 主机配置

在配置 WSL 之前,必须确保 Windows 主机本身已准备就绪。

1. 查找并固定主机局域网 IP

代理服务器的目标地址必须固定。

  • 在 Windows PowerShell 或 CMD 中运行 ipconfig
  • 在你的主网络适配器(如“以太网适配器”或“无线局域网适配器”)下找到 IPv4 地址
  • 建议:在你的路由器管理后台,将此 IP 地址与你的电脑 MAC 地址进行绑定,以防止 IP 地址变动。

本文将以 192.168.0.100 作为示例主机 IP,以 7890 作为 Clash for Windows 的代理端口。请在实际操作中替换为您自己的地址和端口。

2. 为代理端口添加入站防火墙规则

这是最关键的一步。默认情况下,Windows 防火墙可能会阻止来自 WSL(即使它在内部网络)对主机端口的访问,特别是当网络被识别为“公用(Public)”时。创建一个精确的“允许”规则是解决此问题的最佳实践。

  1. 在 Windows 搜索框中,输入“高级安全 Windows Defender 防火墙”并打开它。
  2. 在左侧面板中,点击“入站规则”。
  3. 在右侧“操作”面板中,点击“新建规则…”。
  4. 在向导中,按以下步骤操作:
    • 规则类型:选择“端口”,点击“下一步”。
    • 协议和端口:选择“TCP”,然后在“特定本地端口”中输入您的代理端口,例如 7890。点击“下一步”。
    • 操作:选择“允许连接”,点击“下一步”。
    • 配置文件全部勾选(“域”、“专用”、“公用”),以确保规则在任何网络环境下都生效。点击“下一步”。
    • 名称:为规则起一个易于识别的名称,例如 Allow WSL Clash Proxy (TCP 7890)。点击“完成”。

IMPORTANT

如果不执行此步骤,即使后续所有配置都正确,来自 WSL 和 Docker 的连接也大概率会被 Windows 防火墙丢弃或拒绝。

步骤一:为 WSL Shell 配置代理

此配置将影响您在 WSL 终端中直接使用的命令,如 apt, curl, git, wget 等。

  1. 编辑 Shell 配置文件。根据您的 Shell 类型选择:
# 如果使用默认的 bash
nano ~/.bashrc
 
# 如果使用 zsh
nano ~/.zshrc
  1. 在文件末尾添加以下环境变量。我们同时添加小写和大写版本以获得最佳兼容性。
# Proxy Configuration for Clash for Windows
export http_proxy="http://192.168.0.100:7890"
export https_proxy="http://192.168.0.100:7890"
export no_proxy="localhost,127.0.0.1"
 
export HTTP_PROXY="http://192.168.0.100:7890"
export HTTPS_PROXY="http://192.168.0.100:7890"
export NO_PROXY="localhost,127.0.0.1"
  1. 应用配置。关闭并重开终端,或执行 source ~/.bashrc (或 source ~/.zshrc)。

步骤二:为 Docker 环境配置代理

Docker 的代理配置分为两部分:守护进程(Daemon)和构建/运行环境(Build/Container)。

1. 配置 Docker 守护进程 (Daemon)

此配置主要影响 docker pull, docker push 等与 Docker Hub 交互的命令。

NOTE

直接修改 /etc/docker/daemon.json 是一种方法,但通过 systemd 的覆盖文件 (override) 是更推荐、更模块化的方式。

  1. 使用以下命令,通过一条指令直接创建并写入 systemd 覆盖文件,以避免 vim 操作可能带来的问题。
sudo mkdir -p /etc/systemd/system/docker.service.d/
sudo tee /etc/systemd/system/docker.service.d/override.conf > /dev/null <<EOF
[Service]
Environment="HTTP_PROXY=http://192.168.0.100:7890"
Environment="HTTPS_PROXY=http://192.168.0.100:7890"
Environment="NO_PROXY=localhost,127.0.0.1"
EOF
  1. 应用配置并重启 Docker 服务
# 重新加载 systemd 配置
sudo systemctl daemon-reload
# 重启 Docker 服务以加载新的环境变量
sudo systemctl restart docker

2. 配置 Docker 构建与运行环境

此配置影响 DockerfileRUN 指令(如 RUN apk add ...)以及 docker run 启动的容器内部的网络访问。

  1. 修改 DockerfileDockerfileFROM 指令之后,使用 ENV 指令明确设置代理环境变量。
FROM alpine:3.19
 
# 为构建过程设置代理
ENV HTTP_PROXY="http://192.168.0.100:7890"
ENV HTTPS_PROXY="http://192.168.0.100:7890"
ENV NO_PROXY="localhost,127.0.0.1"
 
# 现在 RUN 指令就可以通过代理下载软件包了
RUN apk update && apk add --no-cache curl git
 
# ... 其他指令 ...
  1. 为运行中的容器设置代理 如果需要在 docker run 启动的容器内部也使用代理,可以通过 -e 参数传入环境变量。
docker run -it --rm \
  -e HTTP_PROXY="http://192.168.0.100:7890" \
  -e HTTPS_PROXY="http://192.168.0.100:7890" \
  ubuntu:latest \
  bash

遵循以上步骤,即可在 WSL2 的标准 NAT 模式下,为你的开发环境建立一套稳定代理配置。