引言
NixOS 的网络配置和整个系统一样是声明式的——所有网卡、地址、路由、防火墙规则都在 configuration.nix 里写死,nixos-rebuild switch 一次生效、可回滚。本文从接口配置讲到防火墙与 VPN,把 NixOS 网络管理的完整工具链给你,每步配可运行配置。
前置:/nixos-configuration/(configuration.nix 基础)、/nix-home-manager/(用户级配置)。本专题聚焦 NixOS 网络层的声明式管理。
目录
- 1. 声明式网络的哲学
- 2. 接口与地址:DHCP 与静态 IP
- 3. WiFi 与无线配置
- 4. DNS 与主机名解析
- 5. 路由与多网卡策略
- 6. 防火墙:nftables 与 iptables
- 7. 端口开放与信任接口
- 8. NAT 与端口转发
- 9. VPN 与 WireGuard 配置
- 10. 速查表与一句话记忆
- 延伸阅读
1. 声明式网络的哲学
1.1 与传统配置对比
| 传统做法 | NixOS 做法 |
|---|---|
ip addr add 手工命令 | networking.interfaces 声明 |
/etc/iptables 脚本 | networking.firewall 声明 |
| 改完重启看效果 | nixos-rebuild switch 原子生效 |
| 出问题难回滚 | 回退到上一代配置 |
1.2 核心模块
networking = {
interfaces # 网卡
wireless # WiFi
firewall # 防火墙
nat # NAT/转发
defaultGateway # 默认网关
nameservers # DNS
}
记忆:NixOS 网络一切皆声明在 networking 模块,rebuild switch 原子生效、可回滚;告别手工命令与脚本。
2. 接口与地址:DHCP 与静态 IP
2.1 自动 DHCP(默认)
networking = {
dhcpcd.enable = true; # 默认开启,自动拿地址
useDHCP = true; # 经典选项(NixOS 21.11+ 建议 useDHCP)
};
2.2 静态 IP
networking.interfaces.eth0 = {
useDHCP = false;
ipv4.addresses = [{
address = "192.168.1.10";
prefixLength = 24;
}];
ipv6.addresses = [{
address = "fd00::10";
prefixLength = 64;
}];
};
networking.defaultGateway = { address = "192.168.1.1"; };
networking.nameservers = [ "1.1.1.1" "8.8.8.8" ];
2.3 多接口
networking.interfaces = {
eth0 = { useDHCP = true; }; # 外网
eth1 = {
ipv4.addresses = [{ address = "10.0.0.10"; prefixLength = 24; }];
}; # 内网
};
记忆:DHCP 默认开;静态 IP 在 networking.interfaces.
.ipv4.addresses 声明,配 defaultGateway 和 nameservers 收尾 。
3. WiFi 与无线配置
3.1 基于 NetworkManager(推荐桌面)
networking.networkmanager.enable = true; # 桌面环境常用
3.2 纯声明式 WiFi(服务器/轻量)
networking.wireless.enable = true;
networking.wireless.networks = {
"MySSID" = {
psk = "my-password";
priority = 5; # 数值越高越优先
};
};
3.3 密钥不外泄:用 wpa_supplicant 引用文件
networking.wireless.networks."MySSID" = {
auth = ''
key_mgmt=WPA-PSK
psk=${secretFile} # 引用 /run/secrets/ 里的密钥文件
'';
};
记忆:桌面用 networkmanager;轻量场景用 networking.wireless 声明网络与 psk;密钥用 secretFile 引用避免写死在配置里。
4. DNS 与主机名解析
4.1 全局 DNS
networking.nameservers = [ "1.1.1.1" "9.9.9.9" ];
networking.search = [ "internal.example.com" ];
4.2 主机名与 hosts
networking.hostName = "web01";
networking.extraHosts = ''
192.168.1.10 db.internal
192.168.1.11 cache.internal
'';
4.3 本地解析服务(dnsmasq 示例)
services.dnsmasq = {
enable = true;
servers = [ "8.8.8.8" "1.1.1.1" ];
settings = {
address = "/.lan/192.168.1.10"; # *.lan 指向内网
};
};
记忆:nameservers 设全局 DNS、search 设搜索域、extraHosts 写静态映射;要内网解析可用 dnsmasq 声明。
5. 路由与多网卡策略
5.1 静态路由
networking.interfaces.eth1 = {
ipv4.addresses = [{ address = "10.0.0.10"; prefixLength = 24; }];
routes = [{
address = "10.1.0.0";
prefixLength = 16;
via = "10.0.0.1";
}];
};
5.2 策略路由(多网关场景)
networking.iproute2.enable = true;
# 按源/目标走不同表,配合 ip rule 声明
networking.extraPkgs = pkgs: [ pkgs.iproute2 ];
记忆:单条路由在接口的 routes 里声明;复杂多网关用策略路由(ip rule + 多路由表)。
6. 防火墙:nftables 与 iptables
6.1 NixOS 声明式防火墙
networking.firewall = {
enable = true;
allowPing = true; # 允许 ping
allowedTCPPorts = [ 80 443 ]; # 开放 HTTP/HTTPS
allowedUDPPorts = [ 53 ]; # DNS
trustedInterfaces = [ "lo" ]; # 回环全信任
allowLocal = true; # 局域网互通
};
6.2 底层是 nftables
NixOS 的 firewall 模块生成 nftables 规则,也可直接声明:
networking.nftables = {
enable = true;
ruleset = ''
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iifname "lo" accept
tcp dport { 80, 443 } accept
}
}
'';
};
记忆:日常用 networking.firewall 声明端口/信任接口即可;底层是 nftables,需要精细控制可直接声明 ruleset。
7. 端口开放与信任接口
7.1 开放规则示例
networking.firewall = {
allowedTCPPorts = [ 80 443 3000 22 ];
# 服务按需开放
interfaces.eth0.allowedTCPPorts = [ 3306 ]; # 只对 eth0 开放数据库
};
7.2 与 systemd 服务联动
services.nginx = {
enable = true;
virtualHosts."example.com" = { listen = [{ addr = "0.0.0.0"; port = 80; }]; };
};
# 防火墙端口独立声明(NixOS 不自动开端口)
networking.firewall.allowedTCPPorts = [ 80 ];
记忆:NixOS 不自动按服务开端口——开端口要显式声明 allowedTCPPorts;可绑定到具体接口缩小暴露面。
8. NAT 与端口转发
8.1 NAT(出站共享)
networking.nat = {
enable = true;
externalInterface = "eth0";
internalInterfaces = [ "eth1" ];
};
8.2 端口转发(入站映射)
networking.firewall.extraCommands = ''
# 将 8080 转发到内网 10.0.0.10:80
ip nat add ...
'';
也可用 nftables 精确声明:
networking.nftables.ruleset = ''
table inet nat {
chain prerouting {
type nat hook prerouting priority -100;
tcp dport 8080 dnat to 10.0.0.10:80
}
chain postrouting {
type nat hook postrouting priority 100;
oifname "eth0" masquerade
}
}
'';
记忆:出站共享用 networking.nat(externalInterface + internalInterfaces);入站转发在防火墙里 dnat/masquerade 声明。
9. VPN 与 WireGuard 配置
9.1 WireGuard(NixOS 原生支持)
networking.wireguard.interfaces = {
wg0 = {
privateKeyFile = "/etc/wireguard/wg0.key";
ips = [ "10.0.0.2/24" ];
peers = [{
publicKey = "xxx...";
allowedIPs = [ "10.0.0.0/24" ];
endpoint = "vpn.example.com:51820";
}];
};
};
9.2 开机自启与防火墙放行
systemd.network = {
enable = true;
networks."wg0" = { matchConfig.Name = "wg0"; networkConfig.DHCP = "no"; };
};
networking.firewall.allowedUDPPorts = [ 51820 ];
9.3 OpenVPN 简单示例
services.openvpn.servers = {
vpn = { config = '' config /etc/openvpn/vpn.conf ''; };
};
记忆:WireGuard 在 networking.wireguard.interfaces 声明私钥/地址/peer,防火墙放行 UDP 端口即可;密钥用 privateKeyFile 引用外部文件。
10. 速查表与一句话记忆
| 场景 | 声明位置 |
|---|---|
| DHCP | networking.useDHCP |
| 静态 IP | networking.interfaces. |
| WiFi | networking.wireless |
| DNS | networking.nameservers |
| 路由 | interfaces. |
| 防火墙 | networking.firewall |
| NAT | networking.nat |
| 转发 | nftables ruleset |
| WireGuard | networking.wireguard.interfaces |
一句话记忆:NixOS 网络全声明在 networking 模块——接口/地址/DNS/路由写在 networking.interfaces 与 nameservers,防火墙用 networking.firewall 声明端口与信任接口(底层 nftables),NAT 用 networking.nat 出站共享、nftables ruleset 做入站转发,VPN 用 networking.wireguard 声明 WireGuard;一切 rebuild switch 原子生效可回滚,密钥用文件引用不写死在配置里。
延伸阅读
- /nixos-configuration/ — configuration.nix 与模块系统
- /nixos-services-containers/ — 服务声明与容器网络
- /nix-deployment-tools/ — 远程部署与集群网络
- /nix-home-manager/ — 用户级配置
- [[linux]] — Linux 网络命令与防火墙实操
- [[network]] — 网络协议原理
- [[security]] — 安全加固与纵深防御
- NixOS 网络配置手册
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。