Files
ubicloud/spec/prog/vnet/update_firewall_rules_spec.rb
Furkan Sahin d503dadcd3 Add private_ipv4 and private_ipv6 utility functions
Our code base had many vm.nics.first.private_ipv(4/6) calls. This commit
moves these into 2 util functions in the vm model and reuses that to
improve code readability and maintainability.
2025-01-30 12:24:20 +01:00

642 lines
26 KiB
Ruby

# frozen_string_literal: true
RSpec.describe Prog::Vnet::UpdateFirewallRules do
subject(:nx) {
described_class.new(st)
}
let(:st) { Strand.new }
let(:ps) {
instance_double(PrivateSubnet)
}
let(:vm) {
vmh = instance_double(VmHost, sshable: instance_double(Sshable, cmd: nil))
nic = instance_double(Nic, private_ipv4: NetAddr::IPv4Net.parse("10.0.0.0/32"), private_ipv6: NetAddr::IPv6Net.parse("fd00::1/128"), ubid_to_tap_name: "tap0")
ephemeral_net6 = NetAddr::IPv6Net.parse("fd00::1/79")
instance_double(Vm, private_subnets: [ps], vm_host: vmh, inhost_name: "x", nics: [nic], ephemeral_net6: ephemeral_net6, load_balancer: nil, private_ipv4: NetAddr::IPv4Net.parse("10.0.0.0/32").network)
}
describe "#before_run" do
it "pops if vm is to be destroyed" do
expect(nx).to receive(:vm).and_return(vm).at_least(:once)
expect(vm).to receive(:destroy_set?).and_return(true)
expect { nx.before_run }.to exit({"msg" => "firewall rule is added"})
end
it "does not pop if vm is not to be destroyed" do
expect(nx).to receive(:vm).and_return(vm).at_least(:once)
expect(vm).to receive(:destroy_set?).and_return(false)
expect { nx.before_run }.not_to exit
end
end
describe "update_firewall_rules" do
it "populates elements if there are fw rules" do
GloballyBlockedDnsname.create_with_id(dns_name: "blockedhost.com", ip_list: Sequel.lit("ARRAY['123.123.123.123'::inet, '2a00:1450:400e:811::200e'::inet]"))
expect(nx).to receive(:vm).and_return(vm).at_least(:once)
expect(vm).to receive(:firewalls).and_return([instance_double(Firewall, name: "fw_table", firewall_rules: [
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("0.0.0.0/0"), port_range: nil),
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("1.1.1.1/32"), port_range: Sequel.pg_range(22..23)),
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("10.10.10.0/26"), port_range: Sequel.pg_range(80..10000)),
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("123.123.123.64/27"), port_range: Sequel.pg_range(8080..12000)),
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("123.123.123.64/26"), port_range: Sequel.pg_range(9000..16000)),
instance_double(FirewallRule, ip6?: true, cidr: NetAddr::IPv6Net.parse("::/0"), port_range: nil),
instance_double(FirewallRule, ip6?: true, cidr: NetAddr::IPv6Net.parse("fd00::1/128"), port_range: Sequel.pg_range(8080..65536)),
instance_double(FirewallRule, ip6?: true, cidr: NetAddr::IPv6Net.parse("fd00::1/64"), port_range: Sequel.pg_range(0..8081)),
instance_double(FirewallRule, ip6?: true, cidr: NetAddr::IPv6Net.parse("fd00::2/64"), port_range: Sequel.pg_range(80..10000))
])])
expect(vm.vm_host.sshable).to receive(:cmd).with("sudo ip netns exec x nft --file -", stdin: <<ADD_RULES)
# An nftables idiom for idempotent re-create of a named entity: merge
# in an empty table (a no-op if the table already exists) and then
# delete, before creating with a new definition.
table inet fw_table;
delete table inet fw_table;
table inet fw_table {
set allowed_ipv4_port_tuple {
type ipv4_addr . inet_service;
flags interval;
elements = {1.1.1.1/32 . 22,10.10.10.0/26 . 80-9999,123.123.123.64/26 . 9000-15999,123.123.123.64/27 . 8080-8999}
}
set allowed_ipv4_lb_dest_set {
type ipv4_addr . inet_service;
flags interval;
}
set allowed_ipv6_port_tuple {
type ipv6_addr . inet_service;
flags interval;
elements = {fd00::/64 . 0-9999,fd00::1/128 . 10000-65535}
}
set allowed_ipv6_lb_dest_set {
type ipv6_addr . inet_service;
flags interval;
}
set private_ipv4_cidrs {
type ipv4_addr;
flags interval;
elements = {
10.0.0.0/32
}
}
set private_ipv6_cidrs {
type ipv6_addr
flags interval
elements = { fd00::1/128 }
}
set globally_blocked_ipv4s {
type ipv4_addr;
flags interval;
elements = {123.123.123.123/32}
}
set globally_blocked_ipv6s {
type ipv6_addr;
flags interval;
elements = {2a00:1450:400e:811::200e/128}
}
flowtable ubi_flowtable {
hook ingress priority filter
devices = { tap0 }
}
chain forward_ingress {
type filter hook forward priority filter; policy drop;
# Offload to ubi_flowtable. This is used to offload already filtered
# traffic to reduce the latency.
meta l4proto { tcp, udp } flow offload @ubi_flowtable
# Destination port 111 is reserved for the portmapper. We block it to
# prevent abuse.
meta l4proto { tcp, udp } th dport 111 drop
# Drop all traffic from globally blocked IPs. This is mainly used to
# block access to malicious IPs that are known to cause issues on the
# internet.
ip saddr @globally_blocked_ipv4s drop
ip6 saddr @globally_blocked_ipv6s drop
ip daddr @globally_blocked_ipv4s drop
ip6 daddr @globally_blocked_ipv6s drop
# If we are using @private_ipv4_cidrs as source address, we allow all
# established,related,new traffic because this is outgoing traffic.
ip saddr @private_ipv4_cidrs ct state established,related,new counter accept
# If we are using clover_ephemeral, that means we are using ipsec. We need
# to allow traffic for the private communication and block via firewall
# rules through @allowed_ipv4_port_tuple and @allowed_ipv6_port_tuple in the
# next section of rules.
ip6 daddr fd00::1:0:0:0/80 counter accept
ip6 saddr fd00::1:0:0:0/80 counter accept
# Allow TCP and UDP traffic for allowed_ipv4_port_tuple and
# allowed_ipv6_port_tuple into the VM using any address, such as;
# - public ipv4
# - private ipv4
# - public ipv6 (guest_ephemeral)
# - private ipv6
# - private clover ephemeral ipv6
ip saddr . tcp dport @allowed_ipv4_port_tuple ct state established,related,new counter accept
ip saddr . udp dport @allowed_ipv4_port_tuple ct state established,related,new counter accept
ip6 saddr . tcp dport @allowed_ipv6_port_tuple ct state established,related,new counter accept
ip6 saddr . udp dport @allowed_ipv6_port_tuple ct state established,related,new counter accept
# Allow outgoing traffic from the VM using the following addresses as
# source address.
ip6 saddr @private_ipv6_cidrs ct state established,related,new counter accept
ip6 saddr fd00::/80 ct state established,related,new counter accept
# Allow incoming traffic to the VM using the following addresses as
# destination address. This is needed to allow the return traffic.
ip6 daddr @private_ipv6_cidrs ct state established,related counter accept
ip6 daddr fd00::/80 ct state established,related counter accept
ip daddr @private_ipv4_cidrs ct state established,related counter accept
# Allow ping for all
ip saddr 0.0.0.0/0 icmp type echo-request counter accept
ip daddr 0.0.0.0/0 icmp type echo-request counter accept
ip saddr 0.0.0.0/0 icmp type echo-reply counter accept
ip daddr 0.0.0.0/0 icmp type echo-reply counter accept
ip6 saddr ::/0 icmpv6 type echo-request counter accept
ip6 daddr ::/0 icmpv6 type echo-request counter accept
ip6 saddr ::/0 icmpv6 type echo-reply counter accept
ip6 daddr ::/0 icmpv6 type echo-reply counter accept
# Allow load balancer traffic
}
}
ADD_RULES
expect { nx.update_firewall_rules }.to exit({"msg" => "firewall rule is added"})
end
it "populates load balancer destination sets and adds related rules" do
GloballyBlockedDnsname.create_with_id(dns_name: "blockedhost.com", ip_list: Sequel.lit("ARRAY['123.123.123.123'::inet, '2a00:1450:400e:811::200e'::inet]"))
expect(nx).to receive(:vm).and_return(vm).at_least(:once)
expect(vm).to receive(:firewalls).and_return([instance_double(Firewall, name: "fw_table", firewall_rules: [
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("0.0.0.0/0"), port_range: nil),
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("1.1.1.1/32"), port_range: Sequel.pg_range(22..23)),
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("10.10.10.0/26"), port_range: Sequel.pg_range(80..10000)),
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("123.123.123.64/27"), port_range: Sequel.pg_range(8080..12000)),
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("123.123.123.64/26"), port_range: Sequel.pg_range(9000..16000)),
instance_double(FirewallRule, ip6?: true, cidr: NetAddr::IPv6Net.parse("::/0"), port_range: nil),
instance_double(FirewallRule, ip6?: true, cidr: NetAddr::IPv6Net.parse("fd00::1/128"), port_range: Sequel.pg_range(8080..65536)),
instance_double(FirewallRule, ip6?: true, cidr: NetAddr::IPv6Net.parse("fd00::1/64"), port_range: Sequel.pg_range(0..8081)),
instance_double(FirewallRule, ip6?: true, cidr: NetAddr::IPv6Net.parse("fd00::2/64"), port_range: Sequel.pg_range(80..10000))
])])
expect(vm).to receive(:id).and_return(1).at_least(:once)
vm2 = instance_double(Vm, id: 2, nics: [instance_double(Nic, private_ipv4: NetAddr::IPv4Net.parse("10.0.0.1/32"), private_ipv6: NetAddr::IPv6Net.parse("fd00::/124"))], private_ipv4: NetAddr::IPv4Net.parse("10.0.0.1/32").network, private_ipv6: NetAddr::IPv6.parse("fd00::2"))
lb = instance_double(LoadBalancer, name: "lb_table", src_port: 443, dst_port: 8443, vms: [vm, vm2])
expect(vm).to receive(:load_balancer).and_return(lb).at_least(:once)
expect(vm.vm_host.sshable).to receive(:cmd).with("sudo ip netns exec x nft --file -", stdin: <<ADD_RULES)
# An nftables idiom for idempotent re-create of a named entity: merge
# in an empty table (a no-op if the table already exists) and then
# delete, before creating with a new definition.
table inet fw_table;
delete table inet fw_table;
table inet fw_table {
set allowed_ipv4_port_tuple {
type ipv4_addr . inet_service;
flags interval;
elements = {1.1.1.1/32 . 22,10.10.10.0/26 . 80-9999,123.123.123.64/26 . 9000-15999,123.123.123.64/27 . 8080-8999}
}
set allowed_ipv4_lb_dest_set {
type ipv4_addr . inet_service;
flags interval;
elements = {10.10.10.0/26 . 8443}
}
set allowed_ipv6_port_tuple {
type ipv6_addr . inet_service;
flags interval;
elements = {fd00::/64 . 0-9999,fd00::1/128 . 10000-65535}
}
set allowed_ipv6_lb_dest_set {
type ipv6_addr . inet_service;
flags interval;
elements = {fd00::/64 . 8443}
}
set private_ipv4_cidrs {
type ipv4_addr;
flags interval;
elements = {
10.0.0.0/32
}
}
set private_ipv6_cidrs {
type ipv6_addr
flags interval
elements = { fd00::1/128 }
}
set globally_blocked_ipv4s {
type ipv4_addr;
flags interval;
elements = {123.123.123.123/32}
}
set globally_blocked_ipv6s {
type ipv6_addr;
flags interval;
elements = {2a00:1450:400e:811::200e/128}
}
flowtable ubi_flowtable {
hook ingress priority filter
devices = { tap0 }
}
chain forward_ingress {
type filter hook forward priority filter; policy drop;
# Offload to ubi_flowtable. This is used to offload already filtered
# traffic to reduce the latency.
meta l4proto { tcp, udp } flow offload @ubi_flowtable
# Destination port 111 is reserved for the portmapper. We block it to
# prevent abuse.
meta l4proto { tcp, udp } th dport 111 drop
# Drop all traffic from globally blocked IPs. This is mainly used to
# block access to malicious IPs that are known to cause issues on the
# internet.
ip saddr @globally_blocked_ipv4s drop
ip6 saddr @globally_blocked_ipv6s drop
ip daddr @globally_blocked_ipv4s drop
ip6 daddr @globally_blocked_ipv6s drop
# If we are using @private_ipv4_cidrs as source address, we allow all
# established,related,new traffic because this is outgoing traffic.
ip saddr @private_ipv4_cidrs ct state established,related,new counter accept
# If we are using clover_ephemeral, that means we are using ipsec. We need
# to allow traffic for the private communication and block via firewall
# rules through @allowed_ipv4_port_tuple and @allowed_ipv6_port_tuple in the
# next section of rules.
ip6 daddr fd00::1:0:0:0/80 counter accept
ip6 saddr fd00::1:0:0:0/80 counter accept
# Allow TCP and UDP traffic for allowed_ipv4_port_tuple and
# allowed_ipv6_port_tuple into the VM using any address, such as;
# - public ipv4
# - private ipv4
# - public ipv6 (guest_ephemeral)
# - private ipv6
# - private clover ephemeral ipv6
ip saddr . tcp dport @allowed_ipv4_port_tuple ct state established,related,new counter accept
ip saddr . udp dport @allowed_ipv4_port_tuple ct state established,related,new counter accept
ip6 saddr . tcp dport @allowed_ipv6_port_tuple ct state established,related,new counter accept
ip6 saddr . udp dport @allowed_ipv6_port_tuple ct state established,related,new counter accept
# Allow outgoing traffic from the VM using the following addresses as
# source address.
ip6 saddr @private_ipv6_cidrs ct state established,related,new counter accept
ip6 saddr fd00::/80 ct state established,related,new counter accept
# Allow incoming traffic to the VM using the following addresses as
# destination address. This is needed to allow the return traffic.
ip6 daddr @private_ipv6_cidrs ct state established,related counter accept
ip6 daddr fd00::/80 ct state established,related counter accept
ip daddr @private_ipv4_cidrs ct state established,related counter accept
# Allow ping for all
ip saddr 0.0.0.0/0 icmp type echo-request counter accept
ip daddr 0.0.0.0/0 icmp type echo-request counter accept
ip saddr 0.0.0.0/0 icmp type echo-reply counter accept
ip daddr 0.0.0.0/0 icmp type echo-reply counter accept
ip6 saddr ::/0 icmpv6 type echo-request counter accept
ip6 daddr ::/0 icmpv6 type echo-request counter accept
ip6 saddr ::/0 icmpv6 type echo-reply counter accept
ip6 daddr ::/0 icmpv6 type echo-reply counter accept
# Allow load balancer traffic
ip saddr . tcp sport { 10.0.0.1 . 443 } ct state established,related,new counter accept
ip6 saddr . tcp sport { fd00::2 . 443 } ct state established,related,new counter accept
# The traffic that is routed to the local VM from the load balancer
# is marked with 0x00B1C100D. We need to allow this traffic to
# the local VM.
meta mark 0x00B1C100D ip saddr . tcp dport @allowed_ipv4_lb_dest_set ct state established,related,new counter accept
meta mark 0x00B1C100D ip6 saddr . tcp dport @allowed_ipv6_lb_dest_set ct state established,related,new counter accept
}
}
ADD_RULES
expect { nx.update_firewall_rules }.to exit({"msg" => "firewall rule is added"})
end
it "populates load balancer destination sets and adds related rules when there is a single load balancer vm" do
GloballyBlockedDnsname.create_with_id(dns_name: "blockedhost.com", ip_list: Sequel.lit("ARRAY['123.123.123.123'::inet, '2a00:1450:400e:811::200e'::inet]"))
expect(nx).to receive(:vm).and_return(vm).at_least(:once)
expect(vm).to receive(:firewalls).and_return([instance_double(Firewall, name: "fw_table", firewall_rules: [
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("0.0.0.0/0"), port_range: nil),
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("1.1.1.1/32"), port_range: Sequel.pg_range(22..23)),
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("10.10.10.0/26"), port_range: Sequel.pg_range(80..10000)),
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("123.123.123.64/27"), port_range: Sequel.pg_range(8080..12000)),
instance_double(FirewallRule, ip6?: false, cidr: NetAddr::IPv4Net.parse("123.123.123.64/26"), port_range: Sequel.pg_range(9000..16000)),
instance_double(FirewallRule, ip6?: true, cidr: NetAddr::IPv6Net.parse("::/0"), port_range: nil),
instance_double(FirewallRule, ip6?: true, cidr: NetAddr::IPv6Net.parse("fd00::1/128"), port_range: Sequel.pg_range(8080..65536)),
instance_double(FirewallRule, ip6?: true, cidr: NetAddr::IPv6Net.parse("fd00::1/64"), port_range: Sequel.pg_range(0..8081)),
instance_double(FirewallRule, ip6?: true, cidr: NetAddr::IPv6Net.parse("fd00::2/64"), port_range: Sequel.pg_range(80..10000))
])])
expect(vm).to receive(:id).and_return(1).at_least(:once)
lb = instance_double(LoadBalancer, name: "lb_table", src_port: 443, dst_port: 8443, vms: [vm])
expect(vm).to receive(:load_balancer).and_return(lb).at_least(:once)
expect(vm.vm_host.sshable).to receive(:cmd).with("sudo ip netns exec x nft --file -", stdin: <<ADD_RULES)
# An nftables idiom for idempotent re-create of a named entity: merge
# in an empty table (a no-op if the table already exists) and then
# delete, before creating with a new definition.
table inet fw_table;
delete table inet fw_table;
table inet fw_table {
set allowed_ipv4_port_tuple {
type ipv4_addr . inet_service;
flags interval;
elements = {1.1.1.1/32 . 22,10.10.10.0/26 . 80-9999,123.123.123.64/26 . 9000-15999,123.123.123.64/27 . 8080-8999}
}
set allowed_ipv4_lb_dest_set {
type ipv4_addr . inet_service;
flags interval;
elements = {10.10.10.0/26 . 8443}
}
set allowed_ipv6_port_tuple {
type ipv6_addr . inet_service;
flags interval;
elements = {fd00::/64 . 0-9999,fd00::1/128 . 10000-65535}
}
set allowed_ipv6_lb_dest_set {
type ipv6_addr . inet_service;
flags interval;
elements = {fd00::/64 . 8443}
}
set private_ipv4_cidrs {
type ipv4_addr;
flags interval;
elements = {
10.0.0.0/32
}
}
set private_ipv6_cidrs {
type ipv6_addr
flags interval
elements = { fd00::1/128 }
}
set globally_blocked_ipv4s {
type ipv4_addr;
flags interval;
elements = {123.123.123.123/32}
}
set globally_blocked_ipv6s {
type ipv6_addr;
flags interval;
elements = {2a00:1450:400e:811::200e/128}
}
flowtable ubi_flowtable {
hook ingress priority filter
devices = { tap0 }
}
chain forward_ingress {
type filter hook forward priority filter; policy drop;
# Offload to ubi_flowtable. This is used to offload already filtered
# traffic to reduce the latency.
meta l4proto { tcp, udp } flow offload @ubi_flowtable
# Destination port 111 is reserved for the portmapper. We block it to
# prevent abuse.
meta l4proto { tcp, udp } th dport 111 drop
# Drop all traffic from globally blocked IPs. This is mainly used to
# block access to malicious IPs that are known to cause issues on the
# internet.
ip saddr @globally_blocked_ipv4s drop
ip6 saddr @globally_blocked_ipv6s drop
ip daddr @globally_blocked_ipv4s drop
ip6 daddr @globally_blocked_ipv6s drop
# If we are using @private_ipv4_cidrs as source address, we allow all
# established,related,new traffic because this is outgoing traffic.
ip saddr @private_ipv4_cidrs ct state established,related,new counter accept
# If we are using clover_ephemeral, that means we are using ipsec. We need
# to allow traffic for the private communication and block via firewall
# rules through @allowed_ipv4_port_tuple and @allowed_ipv6_port_tuple in the
# next section of rules.
ip6 daddr fd00::1:0:0:0/80 counter accept
ip6 saddr fd00::1:0:0:0/80 counter accept
# Allow TCP and UDP traffic for allowed_ipv4_port_tuple and
# allowed_ipv6_port_tuple into the VM using any address, such as;
# - public ipv4
# - private ipv4
# - public ipv6 (guest_ephemeral)
# - private ipv6
# - private clover ephemeral ipv6
ip saddr . tcp dport @allowed_ipv4_port_tuple ct state established,related,new counter accept
ip saddr . udp dport @allowed_ipv4_port_tuple ct state established,related,new counter accept
ip6 saddr . tcp dport @allowed_ipv6_port_tuple ct state established,related,new counter accept
ip6 saddr . udp dport @allowed_ipv6_port_tuple ct state established,related,new counter accept
# Allow outgoing traffic from the VM using the following addresses as
# source address.
ip6 saddr @private_ipv6_cidrs ct state established,related,new counter accept
ip6 saddr fd00::/80 ct state established,related,new counter accept
# Allow incoming traffic to the VM using the following addresses as
# destination address. This is needed to allow the return traffic.
ip6 daddr @private_ipv6_cidrs ct state established,related counter accept
ip6 daddr fd00::/80 ct state established,related counter accept
ip daddr @private_ipv4_cidrs ct state established,related counter accept
# Allow ping for all
ip saddr 0.0.0.0/0 icmp type echo-request counter accept
ip daddr 0.0.0.0/0 icmp type echo-request counter accept
ip saddr 0.0.0.0/0 icmp type echo-reply counter accept
ip daddr 0.0.0.0/0 icmp type echo-reply counter accept
ip6 saddr ::/0 icmpv6 type echo-request counter accept
ip6 daddr ::/0 icmpv6 type echo-request counter accept
ip6 saddr ::/0 icmpv6 type echo-reply counter accept
ip6 daddr ::/0 icmpv6 type echo-reply counter accept
# Allow load balancer traffic
# The traffic that is routed to the local VM from the load balancer
# is marked with 0x00B1C100D. We need to allow this traffic to
# the local VM.
meta mark 0x00B1C100D ip saddr . tcp dport @allowed_ipv4_lb_dest_set ct state established,related,new counter accept
meta mark 0x00B1C100D ip6 saddr . tcp dport @allowed_ipv6_lb_dest_set ct state established,related,new counter accept
}
}
ADD_RULES
expect { nx.update_firewall_rules }.to exit({"msg" => "firewall rule is added"})
end
it "does not pass elements if there are not fw rules" do
# An address to block but not discovered the ip_list, yet.
GloballyBlockedDnsname.create_with_id(dns_name: "blockedhost.com", ip_list: nil)
expect(nx).to receive(:vm).and_return(vm).at_least(:once)
expect(vm).to receive(:firewalls).and_return([])
expect(vm.vm_host.sshable).to receive(:cmd).with("sudo ip netns exec x nft --file -", stdin: <<ADD_RULES)
# An nftables idiom for idempotent re-create of a named entity: merge
# in an empty table (a no-op if the table already exists) and then
# delete, before creating with a new definition.
table inet fw_table;
delete table inet fw_table;
table inet fw_table {
set allowed_ipv4_port_tuple {
type ipv4_addr . inet_service;
flags interval;
}
set allowed_ipv4_lb_dest_set {
type ipv4_addr . inet_service;
flags interval;
}
set allowed_ipv6_port_tuple {
type ipv6_addr . inet_service;
flags interval;
}
set allowed_ipv6_lb_dest_set {
type ipv6_addr . inet_service;
flags interval;
}
set private_ipv4_cidrs {
type ipv4_addr;
flags interval;
elements = {
10.0.0.0/32
}
}
set private_ipv6_cidrs {
type ipv6_addr
flags interval
elements = { fd00::1/128 }
}
set globally_blocked_ipv4s {
type ipv4_addr;
flags interval;
}
set globally_blocked_ipv6s {
type ipv6_addr;
flags interval;
}
flowtable ubi_flowtable {
hook ingress priority filter
devices = { tap0 }
}
chain forward_ingress {
type filter hook forward priority filter; policy drop;
# Offload to ubi_flowtable. This is used to offload already filtered
# traffic to reduce the latency.
meta l4proto { tcp, udp } flow offload @ubi_flowtable
# Destination port 111 is reserved for the portmapper. We block it to
# prevent abuse.
meta l4proto { tcp, udp } th dport 111 drop
# Drop all traffic from globally blocked IPs. This is mainly used to
# block access to malicious IPs that are known to cause issues on the
# internet.
ip saddr @globally_blocked_ipv4s drop
ip6 saddr @globally_blocked_ipv6s drop
ip daddr @globally_blocked_ipv4s drop
ip6 daddr @globally_blocked_ipv6s drop
# If we are using @private_ipv4_cidrs as source address, we allow all
# established,related,new traffic because this is outgoing traffic.
ip saddr @private_ipv4_cidrs ct state established,related,new counter accept
# If we are using clover_ephemeral, that means we are using ipsec. We need
# to allow traffic for the private communication and block via firewall
# rules through @allowed_ipv4_port_tuple and @allowed_ipv6_port_tuple in the
# next section of rules.
ip6 daddr fd00::1:0:0:0/80 counter accept
ip6 saddr fd00::1:0:0:0/80 counter accept
# Allow TCP and UDP traffic for allowed_ipv4_port_tuple and
# allowed_ipv6_port_tuple into the VM using any address, such as;
# - public ipv4
# - private ipv4
# - public ipv6 (guest_ephemeral)
# - private ipv6
# - private clover ephemeral ipv6
ip saddr . tcp dport @allowed_ipv4_port_tuple ct state established,related,new counter accept
ip saddr . udp dport @allowed_ipv4_port_tuple ct state established,related,new counter accept
ip6 saddr . tcp dport @allowed_ipv6_port_tuple ct state established,related,new counter accept
ip6 saddr . udp dport @allowed_ipv6_port_tuple ct state established,related,new counter accept
# Allow outgoing traffic from the VM using the following addresses as
# source address.
ip6 saddr @private_ipv6_cidrs ct state established,related,new counter accept
ip6 saddr fd00::/80 ct state established,related,new counter accept
# Allow incoming traffic to the VM using the following addresses as
# destination address. This is needed to allow the return traffic.
ip6 daddr @private_ipv6_cidrs ct state established,related counter accept
ip6 daddr fd00::/80 ct state established,related counter accept
ip daddr @private_ipv4_cidrs ct state established,related counter accept
# Allow ping for all
ip saddr 0.0.0.0/0 icmp type echo-request counter accept
ip daddr 0.0.0.0/0 icmp type echo-request counter accept
ip saddr 0.0.0.0/0 icmp type echo-reply counter accept
ip daddr 0.0.0.0/0 icmp type echo-reply counter accept
ip6 saddr ::/0 icmpv6 type echo-request counter accept
ip6 daddr ::/0 icmpv6 type echo-request counter accept
ip6 saddr ::/0 icmpv6 type echo-reply counter accept
ip6 daddr ::/0 icmpv6 type echo-reply counter accept
# Allow load balancer traffic
}
}
ADD_RULES
expect { nx.update_firewall_rules }.to exit({"msg" => "firewall rule is added"})
end
end
end