Files
ubicloud/spec/prog/setup_nftables_spec.rb
Furkan Sahin 500e59119d Start using nftables at host to block unused ip addresses
We recently got an e-mail from Hetzner saying our hosts produce a
routing loop with their gateway when receiving packets for IPs not yet
allocated to a VM.

In this case, the host will forward the packet to the default route,
which is the gateway, which in turn, forwards it back to the host,
until TTL is decremented, with much resource expenditure by both
parties.

To address this, I introduce a new nftables definition at the host
level, with the intention of dropping packets to IP addresses with no
VM allocating them. I add a new table of nftables that has two sets
and two rules:
1. The first rule is to accept packets if the daddr is part of the
   first set.
2. The second rule is to drop packets if the daddr is part of the
   second set.

This commit simply sets up the hosts with necessary path creations and
some changes in the /etc/nftables.conf file to accommodate that.

A small note regarding IPv6: We don't need to implement a similar
mechanism for IPv6, because the behavior is different there. When an
IPv4 packet reaches us and we don't know what to do, we simply send it
back to the network from the default route. In IPv6 on the other hand,
we send a neighbor solicitation message to the local network, if there
is a match, they would respond with a link local address, if there is
not, we don't get that response and send back to the client a
destination unreachable message.
2024-02-21 11:40:20 +01:00

26 lines
1.1 KiB
Ruby

# frozen_string_literal: true
require_relative "../model/spec_helper"
RSpec.describe Prog::SetupNftables do
subject(:sn) {
described_class.new(Strand.new(prog: "SetupNftables"))
}
describe "#start" do
it "Sets it up and pops" do
sshable = instance_double(Sshable, host: "1.1.1.1")
vm_host = instance_double(VmHost, ubid: "vmhostubid", assigned_subnets: [
instance_double(Address, cidr: instance_double(NetAddr::IPv4Net, version: 4, network: "1.1.1.1", to_s: "1.1.1.1")),
instance_double(Address, cidr: instance_double(NetAddr::IPv4Net, version: 6, network: "::", to_s: "::")),
instance_double(Address, cidr: instance_double(NetAddr::IPv4Net, version: 4, network: "123.123.123.0/24", to_s: "123.123.123.0/24"))
], sshable: sshable)
expect(sshable).to receive(:cmd).with("sudo host/bin/setup-nftables.rb \\[\\\"123.123.123.0/24\\\"\\]")
expect(sn).to receive(:sshable).and_return(sshable)
expect(sn).to receive(:vm_host).and_return(vm_host).at_least(:once)
expect { sn.start }.to exit({"msg" => "nftables was setup"})
end
end
end