在 NixOS 中设置跨系统 docker 网络很困难

在 NixOS 中设置跨系统 docker 网络很困难

我有一组在本地物理堆栈中的多台服务器上运行的 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=";
            };
          }
        ];
      };

    };
  };
}

据我所知,缺少的关键部分是L2TPsystemd.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 就会默默失败。正确设置Addresswireguard 的字段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=";
            };
          }
        ];
      };

    };
  };
}

相关内容