我有一组在本地物理堆栈中的多台服务器上运行的 docker 服务。出于某些原因,我试图尽可能减少暴露的端口并保证其安全(尽可能使用身份验证、wireguard 和加密连接)。由于系统数量有限,而且并非所有这些系统都是本地的(有一些通向其他位置的虚拟隧道),Swarm 和 Kubernetes 都不是可接受的替代方案。因此,我当前的实现是使用一组 docker-compose 配置和一组支持它们的 wireguard 隧道。
在我的一台服务器严重崩溃之前,它一直运行良好,我决定是时候用 NixOS 替换底层操作系统了。除了处理 Wireguard 之外,Nix 的使用也非常棒。不幸的是,无论出于什么原因,我对 iptables 支持的 wireguard 配置的使用充其量也不稳定,而且我找不到任何日志来说明为什么它在重新启动之间有时有效,有时无效。
不过,我确实发现了一些似乎远的更稳定,扩展起来也更容易:Wireguard 上的 l2tp。我目前计划的布局似乎是生成一组 l2tp 隧道,并使这些隧道上的每个会话成为共享的 docker 网络。目前只有 4 个共享网络,这使得配置非常小,虽然这个虚拟集群中总共有大约 5 个服务器,但它们位于 2 个不同的物理位置,每个位置都有一个堡垒节点。因此,实际的 l2tp 隧道数量保持相对较低。最后一步是使用网桥 netdevs 统一每个 docker 网络的多个隧道,并在该网桥上铺设一个 ipvlan 支持的 docker 网络。
(以上所有内容都是为了涵盖 x-vs-y 可能性。我这样做主要是为了学习练习,但如果有更好、更简单的方法来链接系统之间的 docker/podman 网络,我愿意洗耳恭听。)
以上所有操作在手动设置时(主要是通过ip link
命令等)均按预期工作,鉴于这种情况发生在多个无头服务器上,我已经使用 networkd 设置了所有网络配置。不幸的是,在设置 l2tp netdev 配置时,我似乎在某处缺少关键配置行,并且无法显示实际的 l2tp 网络设备。我似乎也无法在 journalctl 的任何地方找到有关尝试设置设备的任何日志。
我将我的~~作为 pastebin~~ 的关键部分包含在内configuration.nix
(根据要求,将其完整添加到此处),但一些潜在的敏感信息已被删除。
{ config, lib, pkgs, ... }:
{
networking.useNetworkd = true;
systemd.network = {
enable = true;
networks = {
"10-lan1" = {
matchConfig.Name="eno0";
networkConfig.DHCP = "ipv4";
};
"10-wgDocker" = {
matchConfig.Name = "wg-docker";
networkConfig = {
Address = "10.122.1.2/32";
};
};
"10-server2-traefik" = {
matchConfig.Name="server2-traefik";
networkConfig = {
DHCP = "no";
LinkLocalAddressing = "no";
Bridge = "br-traefik";
};
};
};
netdevs = {
"server2" = {
enable = true;
netdevConfig = {
Name = "l2tpServer2";
Kind = "l2tp";
};
l2tpConfig = {
EncapsulationType = "ip";
Local = "10.122.1.2";
PeerTunnelId = 1;
Remote = "10.122.1.3";
TunnelId = 2;
};
l2tpSessions = [
{
l2tpSessionConfig = {
Name = "server2-traefik";
SessionId = 1;
PeerSessionId = 2;
};
}
{
l2tpSessionConfig = {
Name = "server2-redis";
SessionId = 3;
PeerSessionId = 4;
};
}
{
l2tpSessionConfig = {
Name = "server2-postgres";
SessionId = 5;
PeerSessionId = 6;
};
}
];
};
"wg-docker" = {
enable = true;
netdevConfig = {
Name = "wg-docker";
Kind = "wireguard";
};
wireguardConfig = {
ListenPort = 51821;
PrivateKeyFile = "/etc/wireguard/docker-wg/private.key";
};
wireguardPeers = [
{
wireguardPeerConfig = {
AllowedIPs = [
"10.122.1.2/32"
];
Endpoint = "server1.example.com:51821";
PublicKey = "AAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBB=";
};
}
{
wireguardPeerConfig = {
AllowedIPs = [
"10.122.1.3/32"
];
Endpoint = "server2.example.com:51821";
PublicKey = "AAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBB=";
};
}
{
wireguardPeerConfig = {
AllowedIPs = [
"10.122.1.5/32"
];
Endpoint = "server3.example.com:51821";
PublicKey = "AAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBB=";
};
}
];
};
};
};
}
据我所知,缺少的关键部分是L2TP
向systemd.network.networks."10-wgDocker".networkConfig
块中添加一行,但尽管该行存在于标准网络[Network]
段中,但 NixOS 却说它不存在。有没有其他人使用网络上的 NixOS 配置设置了原始 l2tp 配置?我是不是漏掉了什么?整整一个小时的搜索只找到了nixos.org
搜索系统,它告诉我检查systemd.network(5)
哪个没有关于实际完全实现 l2tp 的信息,只有 netdev 配置。
答案1
一旦我弄清楚了为什么 systemd 没有记录任何错误,答案就变得非常简单了,尽管我确实深入研究了为什么它一直显示错误L2TP tunnel with invalid address family configured
。错误来自将现有的 wireguard.conf
文件转换为 networkd 配置。虽然 wireguard 使用字段Address
来设置没有子网的本地地址(10.122.1.2/32
),但 networkd 期望该地址包含子网(10.122.1.2/24
)。这导致了第二个问题,即如果远程地址无法访问,l2tp 就会默默失败。正确设置Address
wireguard 的字段networkConfig
可以让 l2tp 隧道干净地启动。
正确的配置如下:
{ config, lib, pkgs, ... }:
{
networking.useNetworkd = true;
systemd.network = {
enable = true;
networks = {
"10-lan1" = {
matchConfig.Name="eno0";
networkConfig.DHCP = "ipv4";
};
"10-wgDocker" = {
matchConfig.Name = "wg-docker";
networkConfig = {
Address = "10.122.1.2/24";
};
};
"10-server2-traefik" = {
matchConfig.Name="server2-traefik";
networkConfig = {
DHCP = "no";
LinkLocalAddressing = "no";
Bridge = "br-traefik";
};
};
};
netdevs = {
"server2" = {
enable = true;
netdevConfig = {
Name = "l2tpServer2";
Kind = "l2tp";
};
l2tpConfig = {
EncapsulationType = "ip";
Local = "10.122.1.2";
PeerTunnelId = 1;
Remote = "10.122.1.3";
TunnelId = 2;
};
l2tpSessions = [
{
l2tpSessionConfig = {
Name = "server2-traefik";
SessionId = 1;
PeerSessionId = 2;
};
}
{
l2tpSessionConfig = {
Name = "server2-redis";
SessionId = 3;
PeerSessionId = 4;
};
}
{
l2tpSessionConfig = {
Name = "server2-postgres";
SessionId = 5;
PeerSessionId = 6;
};
}
];
};
"wg-docker" = {
enable = true;
netdevConfig = {
Name = "wg-docker";
Kind = "wireguard";
};
wireguardConfig = {
ListenPort = 51821;
PrivateKeyFile = "/etc/wireguard/docker-wg/private.key";
};
wireguardPeers = [
{
wireguardPeerConfig = {
AllowedIPs = [
"10.122.1.2/32"
];
Endpoint = "server1.example.com:51821";
PublicKey = "AAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBB=";
};
}
{
wireguardPeerConfig = {
AllowedIPs = [
"10.122.1.3/32"
];
Endpoint = "server2.example.com:51821";
PublicKey = "AAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBB=";
};
}
{
wireguardPeerConfig = {
AllowedIPs = [
"10.122.1.5/32"
];
Endpoint = "server3.example.com:51821";
PublicKey = "AAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBB=";
};
}
];
};
};
};
}