systemd 限制服务网络权限的核心是启用私有网络命名空间(PrivateNetwork=yes),使其仅见 lo 接口;再通过 RestrictAddressFamilies 限定协议族、IPAddressAllow/IPAddressDeny 控制 IP 范围,并配合 PrivateUsers=yes 和 NoNewPrivileges=yes 防逃逸。

直接用 systemd 限制服务网络权限,核心是切断它与主机网络栈的连接,再按需放行必要通信路径。这不是靠防火墙补漏,而是从进程启动那一刻起就让它“看不见”大部分网络资源。
启用私有网络命名空间
这是最基础也最关键的一步。设置 PrivateNetwork=yes 后,服务会在独立的网络 namespace 中启动:只有 lo 接口可用,无法访问 eth0、wlan0 等真实网卡,也不能看到主机上运行的其他服务端口。
- 对纯本地处理类服务(如日志轮转、配置校验),开这个选项就已足够
- 若服务需对外提供 HTTP,必须配合后续的 IP 白名单或端口映射
- 注意:启用后 systemctl status 查看服务日志可能变慢,因 journal 依赖网络 socket(可加 StandardOutput=journal+console 缓解)
收紧协议族与地址类型
即使开了私有网络,仍可能通过 AF_UNIX 或 AF_NETLINK 做本地提权或信息收集。用 RestrictAddressFamilies 显式限定只允许使用的协议:
-
仅 IPv4 通信:
RestrictAddressFamilies=AF_INET AF_UNIX -
彻底禁用网络:
RestrictAddressFamilies=AF_UNIX(连本地 socket 都保留,适合 IPC 场景) - 避免写
AF_UNSPEC——它等价于“不限制”,会绕过所有控制
控制可访问的 IP 和端口范围
在私有网络基础上,进一步用 IPAddressAllow 和 IPAddressDeny 做白名单过滤:
- 只允许连内网数据库:
IPAddressAllow=192.168.5.0/24+IPAddressDeny=any - 若服务要监听端口,需额外开放绑定能力:
CapabilityBoundingSet=CAP_NET_BIND_SERVICE,否则 bind() 会失败 - 不建议依赖 IPAddressDeny 单独拦截——它只作用于 outbound 连接,inbound 仍需配合防火墙
结合用户命名空间防逃逸
网络隔离若不配用户隔离,攻击者可能通过 /proc/net 或 netlink 探测宿主机状态。加 PrivateUsers=yes 可让服务以 UID 0 运行,但该 root 对宿主机无真实权限:
- 自动创建临时 UID/GID 映射(需提前配置 /etc/subuid 和 /etc/subgid)
- 与 NoNewPrivileges=yes 配合,阻止 execve 获得新权限
- 此时即使服务被攻破,也无法通过 socket 发起提权操作(如利用 AF_NETLINK 修改路由)










