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-tunmacvlan-tun 已正式收口为 TUN-only。初始化界面不会提供 nftables,后端也会拒绝 Docker 环境的 nftables 请求。

当前版本:v0.4.0

当前 Docker 镜像:

ghcr.io/scoltzero/msf:v0.4.0

发布流程同时推送版本化 tag 与 latest;生产部署仍建议固定使用明确的版本 tag。

当前状态

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

初始化预检会阻止缺少 /dev/net/tunCAP_NET_ADMINCAP_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-routetun.auto-detect-interfacetun.route-address,显式保持 tun.dns-hijack=[]tun.auto-redirect=false,并配置 dns.proxy-server-nameserver。DNS 分流仍由 MosDNS 负责,Mihomo 只接管 Fake-IP 和必要公网目标。这意味着 MSF 不会写宿主机 table inet msffwmark 1 table 100ip 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:v0.4.0
    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:v0.4.0
  • 网络: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:v0.4.0

快速启动: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:v0.4.0}
    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:v0.4.0
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_IFACEMSF_DOCKER_SUBNETMSF_DOCKER_GATEWAYMSF_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.028.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。程序不会自动重启 firewalldnftablesufw

先在 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:v0.4.0 容器镜像
MSF_CONTAINER_NAME msf 容器名称
MSF_DOCKER_DATA_DIR $PWD/msf-data 宿主机数据目录
MSF_DOCKER_NETWORK_MODE host-tun host-tunmacvlan-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.5119.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 所在宿主环境中的真实接口,例如 eth0ens18br0 或 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:v0.4.0
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

Install MSF-Docker on Unraid in a few clicks.

Find MSF-Docker in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.

Open the Apps tab on your Unraid server Search Community Apps for MSF-Docker Review the template variables and paths Click Install

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-07-30
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