MSF-Docker

MSF-Docker

Docker app from ScoltZero's Repository

Overview

MSF Docker is a free, open-source, TUN-only DNS and proxy gateway that manages MosDNS and Mihomo through one WebUI. The recommended Unraid deployment gives the container a dedicated LAN IPv4 address on br0.

Docker TUN 部署

English version

Docker host-tun 与 macvlan-tun 已正式收口为 TUN-only。初始化界面不会提供 nftables,后端也会拒绝 Docker 环境的 nftables 请求。

当前稳定镜像:ghcr.io/scoltzero/msf:latest

当前 Docker 镜像:

ghcr.io/scoltzero/msf:latest

发布流程同时推送版本化 tag 与 latest;下方安装命令统一使用 latest,日常升级无需手动修改版本号。

当前状态

  • Docker 版默认使用 Mihomo TUN,不再由 MSF 写入宿主机 nftables 或 policy routing。
  • 支持两种容器网络:host-tun 和 macvlan-tun。
  • host-tun 使用 Docker 宿主机网络命名空间,适合测试、宿主机自身代理,或已经能配置主路由静态路由和宿主机转发的旁路由环境。
  • macvlan-tun 让容器拥有独立 LAN IPv4,适合 Unraid Dockerman / br0 / 自定义网络场景,也是当前 Docker 网关部署更推荐的方式。
  • 运行数据必须映射到宿主机目录;容器内数据目录固定为 /opt/msf,默认示例映射到宿主机 ./msf-data。
  • 容器内禁用 msf update 和 WebUI 自更新安装;镜像升级必须通过 Docker / Compose / 容器管理器完成。

初始化预检会阻止缺少 /dev/net/tun、CAP_NET_ADMIN、CAP_NET_RAW 或无效 Docker 网络模式的部署继续初始化。

运行要求

两种模式都需要 TUN 设备和网络管理权限:

cap_add:
  - NET_ADMIN
  - NET_RAW
devices:
  - /dev/net/tun:/dev/net/tun

Docker 镜像默认设置:

MSF_RUNTIME=docker
MSF_DOCKER_NETWORK_MODE=host-tun
MSF_DOCKER_CLEANUP_NETWORK_ON_EXIT=false

Docker TUN 模式下,Mihomo 配置会启用 tun.auto-route、tun.auto-detect-interface 和 tun.route-address,显式保持 tun.dns-hijack=[]、tun.auto-redirect=false,并配置 dns.proxy-server-nameserver。DNS 分流仍由 MosDNS 负责,Mihomo 只接管 Fake-IP 和必要公网目标。这意味着 MSF 不会写宿主机 table inet msf、fwmark 1 table 100 或 ip rule。如果你把 host-tun 当作旁路网关使用,还需要按下文补充宿主机 FakeIP 路由。

数据目录必须持久化映射:

宿主机目录  ->  容器目录
./msf-data  ->  /opt/msf

MosDNS、Mihomo、Zashboard 下载文件、数据库、配置、日志和用户上传的 Mihomo 配置都会写入 /opt/msf。如果不映射这个目录,容器重建后这些数据会丢失,WebUI 中的组件下载和配置管理也无法可靠工作。

快速启动:host TUN

host TUN 使用宿主机 IP 对外提供 WebUI、DNS 和代理服务。

Docker Compose

仓库根目录已经提供 docker-compose.yml。如果你需要手工创建文件,可以直接复制下面内容保存为 docker-compose.yml:

services:
  msf:
    image: ghcr.io/scoltzero/msf:latest
    container_name: msf
    network_mode: host
    cap_add:
      - NET_ADMIN
      - NET_RAW
    devices:
      - /dev/net/tun:/dev/net/tun
    environment:
      MSF_RUNTIME: docker
      MSF_DATA_DIR: /opt/msf
      MSF_DOCKER_NETWORK_MODE: host-tun
      MSF_DOCKER_CLEANUP_NETWORK_ON_EXIT: "false"
    volumes:
      - ./msf-data:/opt/msf
    restart: unless-stopped
    stop_grace_period: 30s

启动:

mkdir -p msf-data
docker compose up -d

默认 compose 文件使用:

  • 镜像:ghcr.io/scoltzero/msf:latest
  • 网络:host
  • 数据目录:./msf-data:/opt/msf
  • WebUI:http://<宿主机IP>:7777
  • 运行标识:MSF_RUNTIME=docker
  • Docker 网络模式:MSF_DOCKER_NETWORK_MODE=host-tun

普通 Docker 脚本

不适合使用 Docker Compose 的机器可以直接运行:

mkdir -p msf-data
./docker-run.sh

等价的核心参数是:

docker run -d \
  --name msf \
  --network host \
  --cap-add NET_ADMIN \
  --cap-add NET_RAW \
  --device /dev/net/tun:/dev/net/tun \
  --restart unless-stopped \
  --stop-timeout 30 \
  -e MSF_RUNTIME=docker \
  -e MSF_DOCKER_NETWORK_MODE=host-tun \
  -e MSF_DATA_DIR=/opt/msf \
  -v "$PWD/msf-data:/opt/msf" \
  ghcr.io/scoltzero/msf:latest

快速启动:macvlan TUN

macvlan TUN 给容器分配独立 LAN IPv4。路由器侧 DHCP DNS 和 FakeIP 静态路由都应指向这个容器 IPv4,而不是宿主机 IP。

Docker Compose

仓库根目录已经提供 docker-compose.macvlan.yml。如果你需要手工创建文件,可以直接复制下面内容保存为 docker-compose.macvlan.yml:

services:
  msf:
    image: ${MSF_IMAGE:-ghcr.io/scoltzero/msf:latest}
    container_name: ${MSF_CONTAINER_NAME:-msf}
    cap_add:
      - NET_ADMIN
      - NET_RAW
    devices:
      - /dev/net/tun:/dev/net/tun
    environment:
      MSF_RUNTIME: docker
      MSF_DATA_DIR: /opt/msf
      MSF_DOCKER_NETWORK_MODE: macvlan-tun
      MSF_DOCKER_CLEANUP_NETWORK_ON_EXIT: "false"
    volumes:
      - ${MSF_DOCKER_DATA_DIR:-./msf-data}:/opt/msf
    networks:
      msf_macvlan:
        ipv4_address: ${MSF_DOCKER_IPV4_ADDRESS:?set MSF_DOCKER_IPV4_ADDRESS}
    restart: unless-stopped
    stop_grace_period: 30s

networks:
  msf_macvlan:
    name: ${MSF_DOCKER_NETWORK_NAME:-msf-macvlan}
    driver: macvlan
    driver_opts:
      parent: ${MSF_DOCKER_PARENT_IFACE:?set MSF_DOCKER_PARENT_IFACE}
    ipam:
      config:
        - subnet: ${MSF_DOCKER_SUBNET:?set MSF_DOCKER_SUBNET}
          gateway: ${MSF_DOCKER_GATEWAY:?set MSF_DOCKER_GATEWAY}

复制示例环境变量并按你的 LAN 修改:

cp docker.env.example .env

也可以直接复制下面这个 macvlan compose .env 示例保存为 .env 后修改:

MSF_IMAGE=ghcr.io/scoltzero/msf:latest
MSF_CONTAINER_NAME=msf
MSF_DOCKER_DATA_DIR=./msf-data
MSF_DOCKER_NETWORK_NAME=msf-macvlan
MSF_DOCKER_PARENT_IFACE=eth0
MSF_DOCKER_SUBNET=192.168.1.0/24
MSF_DOCKER_GATEWAY=192.168.1.1
MSF_DOCKER_IPV4_ADDRESS=192.168.1.10

macvlan 模式至少需要按你的 LAN 修改 MSF_DOCKER_PARENT_IFACE、MSF_DOCKER_SUBNET、MSF_DOCKER_GATEWAY 和 MSF_DOCKER_IPV4_ADDRESS。

启动:

mkdir -p msf-data
docker compose -f docker-compose.macvlan.yml up -d

普通 Docker 脚本

MSF_DOCKER_NETWORK_MODE=macvlan-tun \
MSF_DOCKER_PARENT_IFACE=eth0 \
MSF_DOCKER_SUBNET=192.168.1.0/24 \
MSF_DOCKER_GATEWAY=192.168.1.1 \
MSF_DOCKER_IPV4_ADDRESS=192.168.1.10 \
./docker-run.sh

脚本会在 msf-macvlan 网络不存在时创建它。可用 MSF_DOCKER_NETWORK_NAME 覆盖网络名。

Unraid Community Applications / Dockerman IPv4 macvlan

仓库提供 Community Applications Docker 模板 packaging/unraid/ca/msf-docker.xml。从 CA 安装 MSF Docker 时,模板会预填以下参数;也可以继续在 Unraid Dockerman 中手工创建容器。

  1. 在 Unraid Docker 设置中启用自定义网络,并选择 macvlan 或你当前系统推荐的自定义网络实现。
  2. 从 CA 安装 MSF Docker,或新建容器并填写镜像 ghcr.io/scoltzero/msf:latest。
  3. Network Type 选择自定义 LAN 网络,例如 br0。
  4. Fixed IP address 填写一个未被 DHCP 分配的静态 IPv4,例如 192.168.1.10。
  5. Extra Parameters 或高级参数添加:
--cap-add NET_ADMIN --cap-add NET_RAW --device /dev/net/tun:/dev/net/tun
  1. 添加环境变量:
变量 值
MSF_RUNTIME docker
MSF_DOCKER_NETWORK_MODE macvlan-tun
MSF_DATA_DIR /opt/msf
  1. 添加路径映射:
宿主机路径 容器路径
/mnt/user/appdata/msf-docker /opt/msf

WebUI 地址为 http://<容器IPv4>:7777。

路由接入

首次打开 WebUI 后完成初始化向导。Docker runtime 下初始化页默认选择 TUN 模式。

路由器侧需要:

  1. DHCP DNS 指向 MSF 地址。
  2. FakeIP 静态路由指向同一个 MSF 地址。

MSF 地址按网络模式选择:

Docker 模式 路由器应指向
host-tun Docker 宿主机 LAN IP
macvlan-tun 容器独立 LAN IPv4;启用 IPv6 时还需要容器可路由 IPv6

默认 FakeIP 网段:

类型 网段
IPv4 28.0.0.0/8
IPv6 f2b0::/18

macvlan 默认验收仍以 IPv4 为主。若启用 IPv6,需要容器拥有可被主路由访问的 IPv6,并在主路由上把 f2b0::/18 指向这个容器 IPv6。完整教程见 路由器接入总览。

host-tun FakeIP 路由持久化

host-tun 共享 Docker 宿主机网络命名空间。主路由把 28.0.0.0/8 静态路由指向 Docker 宿主机后,宿主机还必须把完整 IPv4 FakeIP 网段交给 Mihomo TUN;启用 IPv6 时,f2b0::/18 也需要同样指向 Mihomo TUN。部分环境里 Mihomo 只会给 mihomo 接口生成 28.0.0.0/30,这只能覆盖 28.0.0.0 到 28.0.0.3,客户端拿到 28.0.0.13 这类 FakeIP 时就不会进入 TUN。

新版本会在 Docker host-tun + Mihomo TUN 模式下,在 Mihomo 启动成功后自动补齐 FakeIP IPv4 路由;如果配置中启用了 IPv6,也会自动补齐 FakeIP IPv6 路由。程序还会尝试关闭默认出口网卡的 rp_filter。如果宿主机 /proc/sys 只读、系统防火墙重放了路由规则,或你正在排查旧版本问题,可以继续使用下面的手工命令作为 fallback。程序不会自动重启 firewalld、nftables 或 ufw。

先在 Docker 宿主机上临时验证:

sudo ip route replace 28.0.0.0/8 dev mihomo src 28.0.0.1
# 如果启用了 IPv6:
sudo ip -6 route replace f2b0::/18 dev mihomo src f2b0::1

IFACE="$(ip -4 route show default | awk '/default/ {print $5; exit}')"
echo 0 | sudo tee "/proc/sys/net/ipv4/conf/$IFACE/rp_filter" >/dev/null

sudo sh -c '
if systemctl is-active --quiet firewalld 2>/dev/null; then
  systemctl restart firewalld
elif systemctl is-active --quiet nftables 2>/dev/null; then
  systemctl restart nftables
elif command -v ufw >/dev/null 2>&1; then
  ufw reload
else
  echo "no firewalld/nftables/ufw service detected, skipped"
fi
'

确认 FakeIP 已经走 mihomo:

ip route get 28.0.0.13
# 如果启用了 IPv6:
ip -6 route get f2b0::13
cat "/proc/sys/net/ipv4/conf/$IFACE/rp_filter"

期望看到:

28.0.0.13 dev mihomo src 28.0.0.1
f2b0::13 dev mihomo src f2b0::1
0

临时命令在容器、Mihomo 或宿主机重启后可能丢失。需要持久化时,在 Docker 宿主机上创建 systemd 定时任务。它会定期检查 mihomo 接口是否存在,存在时补齐 FakeIP 路由并关闭出口网卡 rp_filter。如果启用了 IPv6,把脚本里的 ENABLE_IPV6=0 改为 ENABLE_IPV6=1:

sudo tee /usr/local/sbin/msf-host-tun-route >/dev/null <<'EOF'
#!/bin/sh
set -eu

ENABLE_IPV6=0

ip link show mihomo >/dev/null 2>&1 || exit 0

IFACE="$(ip -4 route show default | awk '/default/ {print $5; exit}')"
ip route replace 28.0.0.0/8 dev mihomo src 28.0.0.1
if [ "$ENABLE_IPV6" = "1" ]; then
  ip -6 route replace f2b0::/18 dev mihomo src f2b0::1
fi

if [ -n "$IFACE" ] && [ -w "/proc/sys/net/ipv4/conf/$IFACE/rp_filter" ]; then
  echo 0 > "/proc/sys/net/ipv4/conf/$IFACE/rp_filter"
fi
EOF

sudo chmod +x /usr/local/sbin/msf-host-tun-route

sudo tee /etc/systemd/system/msf-host-tun-route.service >/dev/null <<'EOF'
[Unit]
Description=Apply MSF Docker host-tun FakeIP route

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/msf-host-tun-route
EOF

sudo tee /etc/systemd/system/msf-host-tun-route.timer >/dev/null <<'EOF'
[Unit]
Description=Refresh MSF Docker host-tun FakeIP route

[Timer]
OnBootSec=30s
OnUnitActiveSec=30s
AccuracySec=5s
Unit=msf-host-tun-route.service

[Install]
WantedBy=timers.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now msf-host-tun-route.timer
sudo systemctl start msf-host-tun-route.service

防呆:如果你的系统防火墙服务会缓存或重放转发规则,安装持久化任务后手动重启当前正在使用的防火墙服务:

sudo sh -c '
if systemctl is-active --quiet firewalld 2>/dev/null; then
  systemctl restart firewalld
elif systemctl is-active --quiet nftables 2>/dev/null; then
  systemctl restart nftables
elif command -v ufw >/dev/null 2>&1; then
  ufw reload
else
  echo "no firewalld/nftables/ufw service detected, skipped"
fi
'

脚本变量

docker-run.sh 支持:

变量 默认值 用途
MSF_IMAGE ghcr.io/scoltzero/msf:latest 容器镜像
MSF_CONTAINER_NAME msf 容器名称
MSF_DOCKER_DATA_DIR $PWD/msf-data 宿主机数据目录
MSF_DOCKER_NETWORK_MODE host-tun host-tun 或 macvlan-tun
MSF_DOCKER_NETWORK_NAME msf-macvlan macvlan Docker network 名称
MSF_DOCKER_PARENT_IFACE 无 macvlan 父接口
MSF_DOCKER_SUBNET 无 macvlan IPv4 子网
MSF_DOCKER_GATEWAY 无 macvlan IPv4 网关
MSF_DOCKER_IPV4_ADDRESS 无 容器静态 IPv4

如果同名容器已经存在,先停止并删除旧容器:

docker stop msf
docker rm msf

常见问题

LXC / Proxmox 提示 /dev/net/tun 不存在

如果部署时报错:

error gathering device information while adding custom device "/dev/net/tun": no such file or directory

说明 Docker daemon 所在的运行环境没有 /dev/net/tun。如果 Docker 跑在 LXC 里,需要在 LXC 容器内检查:

ls -l /dev/net/tun
cat /dev/net/tun

正常情况下,cat /dev/net/tun 应返回类似 File descriptor in bad state。如果文件不存在,需要在外层宿主机加载并透传 TUN,例如 Proxmox LXC 可参考:

modprobe tun
features: nesting=1
lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file

修改 LXC 配置后重启容器。不同平台的 LXC 权限模型不完全一样,必要时请使用 privileged LXC 或 VM 测试。

v0.3.7 Docker TUN 出现 DNS / Fake-IP 连接异常

v0.3.7 的 Docker TUN 默认配置存在缺陷:Mihomo 可能把节点服务器域名解析成 28.0.0.x 这类 Fake-IP,随后拨号失败;日志里也可能出现大量 127.0.0.1:8888 connection refused 或节点域名连接超时。

修复版本会统一 Linux TUN 生成逻辑:

  • tun.stack 使用 system。
  • tun.dns-hijack 保持空数组,由 MosDNS 继续负责 DNS 分流。
  • tun.route-address 包含 Fake-IP 网段和必要公网目标。
  • tun.route-exclude-address 排除 LAN、loopback、link-local 和常见国内 DNS。
  • dns.proxy-server-nameserver 使用 223.5.5.5、119.29.29.29,避免节点服务器域名被 Fake-IP 污染。

升级到修复版本后,如果你仍使用生成配置模式,MSF 会在启动时自动修正旧的 TUN / DNS 配置块。若你已经切换到 Mihomo 自定义配置模式,MSF 不会自动覆盖你的文件,请按上面的字段手动调整,或在 WebUI 中恢复为生成配置后重新生成。

macvlan 提示 invalid subinterface vlan name

如果部署时报错类似:

invalid subinterface vlan name MSF_DOCKER_PARENT_IFACE:eth0, example formatting is eth0.10

说明 Docker 收到的 macvlan parent 不是实际网卡名。parent 必须是 Docker 所在宿主环境中的真实接口,例如 eth0、ens18、br0 或 VLAN 子接口 eth0.10。

.env 文件必须使用等号写法:

MSF_DOCKER_PARENT_IFACE=eth0

不要写成:

MSF_DOCKER_PARENT_IFACE:eth0

在 Portainer Stack 里,请把 MSF_DOCKER_PARENT_IFACE 作为环境变量名、eth0 作为值填写,不要把 MSF_DOCKER_PARENT_IFACE:eth0 当成一个完整值。可以先用下面命令确认 compose 展开结果:

MSF_DOCKER_PARENT_IFACE=eth0 \
MSF_DOCKER_SUBNET=192.168.1.0/24 \
MSF_DOCKER_GATEWAY=192.168.1.1 \
MSF_DOCKER_IPV4_ADDRESS=192.168.1.10 \
docker compose -f docker-compose.macvlan.yml config

输出中应能看到:

driver_opts:
  parent: eth0

更新和卸载

Docker 容器内禁用 msf update 和 WebUI 自更新安装。镜像升级应通过拉取新镜像并重建容器完成。

Docker Compose:

docker compose pull
docker compose up -d

普通 Docker:

docker pull ghcr.io/scoltzero/msf:latest
docker stop msf
docker rm msf
./docker-run.sh

卸载时通过 Docker / Compose / 容器管理器删除容器。默认数据目录在宿主机当前目录的 ./msf-data,需要彻底清理时再手动删除该目录。

MosDNS、Mihomo、Zashboard 的组件更新仍可在 WebUI 中使用。

常见端口

Docker TUN 默认不使用 TProxy/Redirect 端口。

端口 用途
7777 MSF WebUI
53/tcp,udp MosDNS
7890 Mihomo HTTP proxy
7891 Mihomo SOCKS proxy
7892 Mihomo mixed proxy
9090 Mihomo controller / Zashboard
9099 MosDNS observability

Requirements

Requires an Unraid custom LAN network such as br0, a dedicated static LAN IPv4 address, and an available /dev/net/tun device. Router DHCP DNS and FakeIP routes must be configured separately.

Related apps

Details

Repository
ghcr.io/scoltzero/msf:latest
Last Updated2026-10-27
First Seen2026-07-29

Runtime arguments

Web UI
http://[IP]:[PORT:7777]
Network
br0
Shell
bash
Privileged
false
Extra Params
--cap-add=NET_ADMIN --cap-add=NET_RAW

Template configuration

App DataPathrw

Persistent MSF configuration, components, databases, and logs.

Target
/opt/msf
Default
/mnt/user/appdata/msf-docker
Value
/mnt/user/appdata/msf-docker
TUN DeviceDevice

Pass the host TUN device into the container.

Target
/dev/net/tun
Value
/dev/net/tun
WebUI PortPorttcp

MSF WebUI port. Keep 7777 when using a custom br0 address.

Target
7777
Default
7777
Value
7777
RuntimeVariable

Identifies this installation as a Docker runtime.

Target
MSF_RUNTIME
Default
docker
Value
docker
Data DirectoryVariable

Persistent data directory inside the container.

Target
MSF_DATA_DIR
Default
/opt/msf
Value
/opt/msf
Docker Network ModeVariable

MSF TUN networking mode for an Unraid custom LAN address.

Target
MSF_DOCKER_NETWORK_MODE
Default
macvlan-tun
Value
macvlan-tun
Network CleanupVariable

Keep host and container networking intact when MSF exits.

Target
MSF_DOCKER_CLEANUP_NETWORK_ON_EXIT
Default
false
Value
false