diff --git a/manifests/interface.pp b/manifests/interface.pp index de98904..5afe350 100644 --- a/manifests/interface.pp +++ b/manifests/interface.pp @@ -124,10 +124,6 @@ } if $manage_firewall { - $daddr = empty($destination_addresses) ? { - true => undef, - default => $destination_addresses, - } # ToDo: It would be nice if this would be a parameter if $endpoint =~ /:(\d+)$/ { $endpoint_port = Integer($1) @@ -136,57 +132,104 @@ } $source_addresses.each |$index1, $saddr| { if $saddr =~ Stdlib::IP::Address::V4 { - $daddr.each |$index2, $_daddr| { - if $_daddr =~ Stdlib::IP::Address::V4 { - nftables::simplerule { "allow_in_wg_${interface}-${index1}${index2}": - action => 'accept', - comment => "Allow traffic from interface ${input_interface} from IP ${saddr} for wireguard tunnel ${interface}", - dport => $dport, - sport => $endpoint_port, - proto => 'udp', - daddr => $_daddr, - saddr => $saddr, - iifname => $input_interface, - notify => Service['systemd-networkd'], - } - nftables::simplerule { "allow_out_wg_${interface}-${index1}${index2}": - action => 'accept', - comment => "Allow traffic out interface ${input_interface} to IP ${saddr} for wireguard tunnel ${interface}", - dport => $endpoint_port, - sport => $dport, - proto => 'udp', - daddr => $saddr, - saddr => $_daddr, - oifname => $input_interface, - chain => 'default_out', - notify => Service['systemd-networkd'], + if empty($destination_addresses) { + nftables::simplerule { "allow_in_wg_${interface}-${index1}": + action => 'accept', + comment => "Allow traffic from interface ${input_interface} from IP ${saddr} for wireguard tunnel ${interface}", + dport => $dport, + sport => $endpoint_port, + proto => 'udp', + saddr => $saddr, + iifname => $input_interface, + notify => Service['systemd-networkd'], + } + nftables::simplerule { "allow_out_wg_${interface}-${index1}": + action => 'accept', + comment => "Allow traffic out interface ${input_interface} to IP ${saddr} for wireguard tunnel ${interface}", + dport => $endpoint_port, + sport => $dport, + proto => 'udp', + daddr => $saddr, + oifname => $input_interface, + chain => 'default_out', + notify => Service['systemd-networkd'], + } + } else { + $destination_addresses.each |$index2, $_daddr| { + if $_daddr =~ Stdlib::IP::Address::V4 { + nftables::simplerule { "allow_in_wg_${interface}-${index1}${index2}": + action => 'accept', + comment => "Allow traffic from interface ${input_interface} from IP ${saddr} for wireguard tunnel ${interface}", + dport => $dport, + sport => $endpoint_port, + proto => 'udp', + daddr => $_daddr, + saddr => $saddr, + iifname => $input_interface, + notify => Service['systemd-networkd'], + } + nftables::simplerule { "allow_out_wg_${interface}-${index1}${index2}": + action => 'accept', + comment => "Allow traffic out interface ${input_interface} to IP ${saddr} for wireguard tunnel ${interface}", + dport => $endpoint_port, + sport => $dport, + proto => 'udp', + daddr => $saddr, + saddr => $_daddr, + oifname => $input_interface, + chain => 'default_out', + notify => Service['systemd-networkd'], + } } } } } else { - $daddr.each |$index2, $_daddr| { - if $_daddr =~ Stdlib::IP::Address::V6 { - nftables::simplerule { "allow_in_wg_${interface}-${index1}${index2}": - action => 'accept', - comment => "Allow traffic from interface ${input_interface} from IP ${saddr} for wireguard tunnel ${interface}", - dport => $dport, - proto => 'udp', - daddr => $_daddr, - saddr => $saddr, - iifname => $input_interface, - notify => Service['systemd-networkd'], - } - nftables::simplerule { "allow_out_wg_${interface}-${index1}${index2}": - action => 'accept', - comment => "Allow traffic out interface ${input_interface} to IP ${saddr} for wireguard tunnel ${interface}", - dport => $endpoint_port, - sport => $dport, - proto => 'udp', - daddr => $saddr, - saddr => $_daddr, - oifname => $input_interface, - chain => 'default_out', - notify => Service['systemd-networkd'], + if empty($destination_addresses) { + nftables::simplerule { "allow_in_wg_${interface}-${index1}": + action => 'accept', + comment => "Allow traffic from interface ${input_interface} from IP ${saddr} for wireguard tunnel ${interface}", + dport => $dport, + proto => 'udp', + saddr => $saddr, + iifname => $input_interface, + notify => Service['systemd-networkd'], + } + nftables::simplerule { "allow_out_wg_${interface}-${index1}": + action => 'accept', + comment => "Allow traffic out interface ${input_interface} to IP ${saddr} for wireguard tunnel ${interface}", + dport => $endpoint_port, + sport => $dport, + proto => 'udp', + daddr => $saddr, + oifname => $input_interface, + chain => 'default_out', + notify => Service['systemd-networkd'], + } + } else { + $destination_addresses.each |$index2, $_daddr| { + if $_daddr =~ Stdlib::IP::Address::V6 { + nftables::simplerule { "allow_in_wg_${interface}-${index1}${index2}": + action => 'accept', + comment => "Allow traffic from interface ${input_interface} from IP ${saddr} for wireguard tunnel ${interface}", + dport => $dport, + proto => 'udp', + daddr => $_daddr, + saddr => $saddr, + iifname => $input_interface, + notify => Service['systemd-networkd'], + } + nftables::simplerule { "allow_out_wg_${interface}-${index1}${index2}": + action => 'accept', + comment => "Allow traffic out interface ${input_interface} to IP ${saddr} for wireguard tunnel ${interface}", + dport => $endpoint_port, + sport => $dport, + proto => 'udp', + daddr => $saddr, + saddr => $_daddr, + oifname => $input_interface, + chain => 'default_out', + notify => Service['systemd-networkd'], + } } } } diff --git a/spec/defines/interface_spec.rb b/spec/defines/interface_spec.rb index 49ce38a..2587f25 100644 --- a/spec/defines/interface_spec.rb +++ b/spec/defines/interface_spec.rb @@ -29,6 +29,7 @@ end it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_wireguard__provider__systemd('as1234') } end context 'with required params (public_key) and without firewall rules' do @@ -517,6 +518,34 @@ it { is_expected.to contain_file("/etc/systemd/network/#{title}.netdev").with_content(expected_netdev_content_allow) } end + + # the following is a usecase for clients with dynamic ip addresses + # in those cases we don't want to match the dst IP for incoming packets + # so destination_addresses is an empty array. We need to ensure we create + # firewall rules, but without dst + context 'without destination we still create firewall rules' do + let :pre_condition do + 'class {"systemd": + manage_networkd => true + }' + end + let :params do + { + endpoint: 'wireguard.example.com:1234', + public_key: 'blabla==', + manage_firewall: true, + destination_addresses: [], + addresses: [{ 'Address' => '192.0.2.1/24' }], + source_addresses: ['fe80::1', '127.0.0.1'], + } + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_nftables__simplerule('allow_in_wg_as1234-0') } + it { is_expected.to contain_nftables__simplerule('allow_in_wg_as1234-1') } + it { is_expected.to contain_nftables__simplerule('allow_out_wg_as1234-0') } + it { is_expected.to contain_nftables__simplerule('allow_out_wg_as1234-1') } + end end end end