-
Notifications
You must be signed in to change notification settings - Fork 0
wire: wireguard interface #233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package 'systemd-container' | ||
| package 'mmdebstrap' | ||
|
|
||
| directory '/var/lib/machines' do | ||
| owner 'root' | ||
| group 'root' | ||
| mode '0700' | ||
| end | ||
|
|
||
| directory '/etc/systemd/nspawn' do | ||
| owner 'root' | ||
| group 'root' | ||
| mode '0755' | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| package 'tpm2-tools' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| node.reverse_merge!( | ||
| systemd_networkd: { | ||
| migrate_netplan: false, | ||
| }, | ||
| wire: { | ||
| interfaces: { | ||
| loopback: { | ||
| address4: %w[10.33.0.41], | ||
| address6: %w[2001:df0:8500:ca00::41], | ||
| }, | ||
| management: { | ||
| name: 'me0', | ||
| path: '*14.0-usb-0:*:1.0', | ||
| duid: '00:00:ba:2c:33:00:41', | ||
| }, | ||
| overlay: { | ||
| name: 'enp3s0', | ||
| ipv6_token: 'static:::8888:aaaa:0:1', | ||
| }, | ||
| downstream: { | ||
| name: 'enp2s0', | ||
| # local_as: 65026, | ||
| # peer_as: 65030, | ||
| # link4: { | ||
| # local: '10.33.22.64', | ||
| # peer: '10.33.22.65', | ||
| # }, | ||
| # link6: { | ||
| # local: '2001:df0:8500:ca22:64::a', | ||
| # peer: '2001:df0:8500:ca22:64::b', | ||
| # }, | ||
| }, | ||
| }, | ||
| tunnels: { | ||
| wg_wire03: { | ||
| listen_port: 8703, | ||
| peer_endpoint: 'rknet-wire-03.i.open.ad.jp:8701', | ||
| peer_public_key: 'TADiMxPz1fqm5LjWH44/Q1kpt9XkAyl+umB8OEJgoGA=', # dummy | ||
| link4: { | ||
| local: '10.33.22.90', | ||
| peer: '10.33.22.91', | ||
| }, | ||
| link6: { | ||
| local: '2001:df0:8500:ca22:90::a', | ||
| peer: '2001:df0:8500:ca22:90::b', | ||
| }, | ||
| }, | ||
| }, | ||
| }, | ||
| ) | ||
|
|
||
| include_role 'wire' | ||
| include_cookbook 'bluetooth-getty' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| node.reverse_merge!( | ||
| systemd_networkd: { | ||
| manage_foreign_routes: false, | ||
| }, | ||
| wire: { | ||
| }, | ||
| bird: { | ||
| router_id: [*node.dig(:wire, :interfaces, :loopback).fetch(:address4)].first, | ||
| }, | ||
| ) | ||
|
|
||
| include_role 'base' | ||
| include_cookbook 'ruby' | ||
|
|
||
| include_cookbook 'cpufreq' | ||
| #include_cookbook 'nftables' | ||
|
|
||
| package 'wireguard-tools' | ||
|
|
||
|
|
||
| %w[ | ||
| 00-lo.network | ||
| ].each do |fname| | ||
| template "/etc/systemd/network/#{fname}" do | ||
| owner 'root' | ||
| group 'root' | ||
| mode '0644' | ||
| notifies :restart, 'service[systemd-networkd]' | ||
| end | ||
| end | ||
|
|
||
| if node.dig(:wire, :interfaces, :management) | ||
| %w[ | ||
| 00-management.network | ||
| 00-management.link | ||
| ].each do |fname| | ||
| template "/etc/systemd/network/#{fname}" do | ||
| owner 'root' | ||
| group 'root' | ||
| mode '0644' | ||
| notifies :restart, 'service[systemd-networkd]' | ||
| end | ||
| end | ||
| end | ||
|
|
||
| file "/etc/wire.json" do | ||
| content "#{JSON.pretty_generate(node[:wire])}\n" | ||
| owner 'root' | ||
| group 'root' | ||
| mode '0644' | ||
| end | ||
|
|
||
| include_recipe './key.rb' | ||
| include_recipe './overlay.rb' | ||
| include_recipe './wireguard.rb' | ||
|
|
||
| service 'systemd-nspawn@overlay.service' do | ||
| action [:enable, :start] | ||
| end | ||
|
|
||
|
|
||
|
|
||
| # template '/etc/nftables/plat.conf' do | ||
| # owner 'root' | ||
| # group 'root' | ||
| # mode '0644' | ||
| # notifies :reload, 'service[nftables]' | ||
| # end | ||
| # | ||
| # template '/etc/bird/bird.conf.d/plat.conf' do | ||
| # owner 'root' | ||
| # group 'bird' | ||
| # mode '0644' | ||
| # notifies :reload, 'service[bird]' | ||
| # end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| include_cookbook 'tpm' | ||
|
|
||
| execute 'wg genkey' do | ||
| command "touch /etc/wire.key; chmod 600 /etc/wire.key; wg genkey|sudo systemd-creds encrypt --name network.wireguard.private.default --with-key 'host+tpm2' - /etc/wire.key" | ||
| not_if 'test -e /etc/wire.key' | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| include_cookbook 'systemd-container' | ||
|
|
||
| execute 'mmdebstrap for overlay' do | ||
| command <<~EOF | ||
| set -xe | ||
| mmdebstrap \ | ||
| --include=dbus,libpam-systemd,libnss-systemd,systemd,systemd-resolved,iproute2,iputils-ping,curl,wireguard-tools \ | ||
| --dpkgopt='path-exclude=/usr/share/man/*' \ | ||
| --dpkgopt='path-include=/usr/share/man/man[1-9]/*' \ | ||
| --dpkgopt='path-exclude=/usr/share/locale/*' \ | ||
| --dpkgopt='path-include=/usr/share/locale/locale.alias' \ | ||
| --dpkgopt='path-exclude=/usr/share/doc/*' \ | ||
| --dpkgopt='path-include=/usr/share/doc/*/copyright' \ | ||
| --dpkgopt='path-include=/usr/share/doc/*/changelog.Debian.*' \ | ||
| --variant=essential "$(lsb_release -sc)" /root/overlay.tar | ||
| importctl import-tar --class=machine /root/overlay.tar overlay | ||
| EOF | ||
| not_if 'test -e /var/lib/machines/overlay/etc/hostname' | ||
| end | ||
|
|
||
| template '/etc/systemd/nspawn/overlay.nspawn' do | ||
| owner 'root' | ||
| group 'root' | ||
| mode '0644' | ||
| end | ||
|
|
||
| directory '/etc/systemd/system/systemd-nspawn@overlay.service.d' do | ||
| owner 'root' | ||
| group 'root' | ||
| mode '0755' | ||
| end | ||
|
|
||
| template '/etc/systemd/system/systemd-nspawn@overlay.service.d/dropin.conf' do | ||
| owner 'root' | ||
| group 'root' | ||
| mode '0644' | ||
| notifies :run, 'execute[systemctl daemon-reload]', :immediately | ||
| end | ||
|
|
||
| directory '/var/lib/machines/overlay/etc/systemd/network' do | ||
| owner 'root' | ||
| group 'root' | ||
| mode '0755' | ||
| end | ||
|
|
||
| template '/var/lib/machines/overlay/etc/systemd/network/00-overlay.network' do | ||
| owner 'root' | ||
| group 'root' | ||
| mode '0644' | ||
| end | ||
|
|
||
| execute 'chroot /var/lib/machines/overlay systemctl enable systemd-networkd.service' do | ||
| not_if 'chroot /var/lib/machines/overlay systemctl is-enabled systemd-networkd.service' | ||
| end | ||
|
|
||
| execute 'chroot /var/lib/machines/overlay systemctl enable systemd-resolved.service' do | ||
| not_if 'chroot /var/lib/machines/overlay systemctl is-enabled systemd-resolved.service' | ||
| end | ||
|
|
||
| execute 'chroot /var/lib/machines/overlay systemctl enable systemd-networkd-wait-online.service' do | ||
| not_if 'chroot /var/lib/machines/overlay systemctl is-enabled systemd-networkd-wait-online.service' | ||
| end | ||
|
|
||
| execute 'chroot /var/lib/machines/overlay systemctl enable network-online.target' do | ||
| not_if 'chroot /var/lib/machines/overlay systemctl is-enabled network-online.target' | ||
| end | ||
|
|
||
| service 'systemd-nspawn@overlay.service' do | ||
| action [:enable, :start] | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| <%- | ||
| addrs4 = node.dig(:wire, :interfaces, :loopback).fetch(:address4) | ||
| addrs6 = node.dig(:wire, :interfaces, :loopback).fetch(:address6) | ||
| -%> | ||
| [Match] | ||
| Name=lo | ||
|
|
||
| [Network] | ||
| <%- addrs4.each do |addr| -%> | ||
| Address=<%= addr %>/32 | ||
| <%- end -%> | ||
| <%- addrs6.each do |addr| -%> | ||
| Address=<%= addr %>/128 | ||
| <%- end -%> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| <%- iface = node.dig(:wire, :interfaces, :management) -%> | ||
| [Match] | ||
| Path=<%= iface.fetch(:path) %> | ||
|
|
||
| [Link] | ||
| Name=<%= iface.fetch(:name) %> | ||
| AlternativeNamesPolicy=mac |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| <%- iface = node.dig(:wire, :interfaces, :management) -%> | ||
| [Match] | ||
| Name=<%= iface.fetch(:name) %> | ||
|
|
||
| [Network] | ||
| IPForward=no | ||
| IPv6AcceptRA=yes | ||
| DHCP=ipv4 | ||
| LLDP=yes | ||
| EmitLLDP=yes | ||
| LinkLocalAddressing=yes | ||
|
|
||
| [DHCPv4] | ||
| SendHostname=yes | ||
| UseDNS=yes | ||
| UseMTU=yes | ||
| ClientIdentifier=duid | ||
| DUIDType=vendor | ||
| DUIDRawData=<%= iface.fetch(:duid) %> | ||
|
|
||
|
|
||
| [IPv6AcceptRA] | ||
| UseDNS=yes | ||
| UseMTU=yes |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| <%- iface = @attr -%> | ||
| <%- link4 = iface.fetch(:link4) -%> | ||
| <%- link6 = iface.fetch(:link6) -%> | ||
| [Match] | ||
| Name=<%= @name %> | ||
|
|
||
| [Network] | ||
| IPv4Forwarding=yes | ||
| IPv6Forwarding=yes | ||
| LLDP=yes | ||
| EmitLLDP=yes | ||
|
|
||
| [Address] | ||
| Address=<%= link4.fetch(:local) %>/32 | ||
| Peer=<%= link4.fetch(:peer) %>/32 | ||
|
|
||
| [Address] | ||
| Address=<%= link6.fetch(:local) %>/128 | ||
| Peer=<%= link6.fetch(:peer) %>/128 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| [Exec] | ||
| Hostname=overlay | ||
| LinkJournal=try-host | ||
| PrivateUsers=no | ||
|
|
||
| [Files] | ||
| ReadOnly=yes | ||
|
|
||
| [Network] | ||
| Private=yes | ||
| Interface=<%= node.dig(:wire, :interfaces, :overlay).fetch(:name) %> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| [Unit] | ||
| Description=rk-move-overlay-wg-iface | ||
| After=systemd-nspawn@overlay.service | ||
|
|
||
| [Service] | ||
| Type=oneshot | ||
| ExecStart=/usr/bin/rk-move-overlay-wg-iface | ||
|
|
||
| [Install] | ||
| WantedBy=systemd-nspawn@overlay.service | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| [Service] | ||
| ExecStart= | ||
| ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --network-veth -U --settings=override --machine=%i --load-credential=network.wireguard.private.default:%d/network.wireguard.private.default | ||
| LoadCredentialEncrypted=network.wireguard.private.default:/etc/wire.key |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| #!/usr/bin/env ruby | ||
| require 'fileutils' | ||
| require 'json' | ||
|
|
||
| config = JSON.parse(File.read('/etc/wire.json')) | ||
| tunnel_ifaces = config.fetch('tunnels', {}).keys.sort | ||
|
|
||
| puts "Waiting for overlay container to be online" | ||
| 10.times do |i| | ||
| if system(*%w(systemd-run --machine overlay --wait --quiet --pipe --collect id)) | ||
| break | ||
| else | ||
| sleep 2 | ||
| end | ||
| end | ||
|
Comment on lines
+9
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: The retry loop in Suggested FixAfter the Prompt for AI AgentDid we get this right? 👍 / 👎 to inform future reviews. |
||
| puts "Waiting for overlay network to be online" | ||
| system(*%w(systemd-run --machine overlay --wait --quiet --pipe --collect /lib/systemd/systemd-networkd-wait-online --ipv6 -o routable --dns), exception: true) | ||
|
|
||
| # Reconfigure tunnels to populate Endpoint= where DNS name is specified | ||
| tunnel_ifaces.each do |iface| | ||
| puts "Reconfiguring #{iface} in overlay" | ||
| system(*%w(systemd-run --machine overlay --wait --quiet --pipe --collect networkctl reconfigure), iface) | ||
| end | ||
|
|
||
| leader = IO.popen(%w(machinectl show -p Leader --value overlay), 'r', &:read) | ||
| puts "Leader PID: #{leader.inspect}" | ||
| leader_i = leader.to_i | ||
| raise "Failed to get leader PID" if leader_i <= 0 | ||
|
|
||
| FileUtils.mkdir_p '/var/run/netns' | ||
| FileUtils.rm_f '/var/run/netns/overlay' rescue nil | ||
| FileUtils.ln_s "/proc/#{leader_i}/ns/net", "/var/run/netns/overlay" | ||
|
|
||
| system(*%w(ip netns exec overlay ip link), exception: true) | ||
|
|
||
| tunnel_ifaces.each do |iface| | ||
| if File.exist?(File.join("/", "sys", "class", "net", iface)) | ||
| puts "Interface #{iface} already exists" | ||
| system(*%w(ip link delete ), iface, exception: true) | ||
| end | ||
| puts "Acquiring #{iface}" | ||
| system(*%w(ip netns exec overlay ip link set), iface, *%w(netns 1), exception: true) | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| [Match] | ||
| Name=<%= node.dig(:wire, :interfaces, :overlay).fetch(:name) %> | ||
|
|
||
| [Link] | ||
| RequiredForOnline=routable | ||
|
|
||
| [Network] | ||
| DHCP=ipv6 | ||
| IPv6AcceptRA=yes | ||
| IPv4Forwarding=off | ||
| IPv6Forwarding=off | ||
|
|
||
| <%= node.fetch(:wire).fetch(:tunnels, {}).each_key.map { |name| "Tunnel=#{name}" }.join("\n") %> | ||
|
|
||
| [IPv6AcceptRA] | ||
| Token=<%= node.dig(:wire, :interfaces, :overlay).fetch(:ipv6_token) %> | ||
|
|
||
| [DHCPv6] | ||
| UseDNS=yes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: The
rk-move-overlay-wg-iface.servicedoes not re-run on container restart, which will break WireGuard tunnels because the interfaces are not moved to the host namespace.Severity: HIGH
Suggested Fix
To ensure the service's lifecycle is tied to the container's, add
RemainAfterExit=yesto the[Service]section andPartOf=systemd-nspawn@overlay.serviceto the[Install]section of the service file. This will cause the service to be stopped and restarted along with the container.Prompt for AI Agent
Did we get this right? 👍 / 👎 to inform future reviews.