util/linuxfw: verify that IPv6 if available if (#12598)

nftable runner for an IPv6 address gets requested.

Updates tailscale/tailscale#12215

Signed-off-by: Irbe Krumina <irbe@tailscale.com>
pull/12602/head
Irbe Krumina 5 months ago committed by GitHub
parent d91e5c25ce
commit 24a40f54d9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -70,15 +70,18 @@ type nftable struct {
// https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains // https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains
type nftablesRunner struct { type nftablesRunner struct {
conn *nftables.Conn conn *nftables.Conn
nft4 *nftable // IPv4 tables nft4 *nftable // IPv4 tables, never nil
nft6 *nftable // IPv6 tables nft6 *nftable // IPv6 tables or nil if the system does not support IPv6
v6Available bool // whether the host supports IPv6 v6Available bool // whether the host supports IPv6
} }
func (n *nftablesRunner) ensurePreroutingChain(dst netip.Addr) (*nftables.Table, *nftables.Chain, error) { func (n *nftablesRunner) ensurePreroutingChain(dst netip.Addr) (*nftables.Table, *nftables.Chain, error) {
polAccept := nftables.ChainPolicyAccept polAccept := nftables.ChainPolicyAccept
table := n.getNFTByAddr(dst) table, err := n.getNFTByAddr(dst)
if err != nil {
return nil, nil, fmt.Errorf("error setting up nftables for IP family of %v: %w", dst, err)
}
nat, err := createTableIfNotExist(n.conn, table.Proto, "nat") nat, err := createTableIfNotExist(n.conn, table.Proto, "nat")
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("error ensuring nat table: %w", err) return nil, nil, fmt.Errorf("error ensuring nat table: %w", err)
@ -192,7 +195,10 @@ func (n *nftablesRunner) DNATNonTailscaleTraffic(tunname string, dst netip.Addr)
func (n *nftablesRunner) AddSNATRuleForDst(src, dst netip.Addr) error { func (n *nftablesRunner) AddSNATRuleForDst(src, dst netip.Addr) error {
polAccept := nftables.ChainPolicyAccept polAccept := nftables.ChainPolicyAccept
table := n.getNFTByAddr(dst) table, err := n.getNFTByAddr(dst)
if err != nil {
return fmt.Errorf("error setting up nftables for IP family of %v: %w", dst, err)
}
nat, err := createTableIfNotExist(n.conn, table.Proto, "nat") nat, err := createTableIfNotExist(n.conn, table.Proto, "nat")
if err != nil { if err != nil {
return fmt.Errorf("error ensuring nat table exists: %w", err) return fmt.Errorf("error ensuring nat table exists: %w", err)
@ -272,7 +278,10 @@ func (n *nftablesRunner) AddSNATRuleForDst(src, dst netip.Addr) error {
// we don't want to race with wgengine for rule ordering within chains. // we don't want to race with wgengine for rule ordering within chains.
func (n *nftablesRunner) ClampMSSToPMTU(tun string, addr netip.Addr) error { func (n *nftablesRunner) ClampMSSToPMTU(tun string, addr netip.Addr) error {
polAccept := nftables.ChainPolicyAccept polAccept := nftables.ChainPolicyAccept
table := n.getNFTByAddr(addr) table, err := n.getNFTByAddr(addr)
if err != nil {
return fmt.Errorf("error setting up nftables for IP family of %v: %w", addr, err)
}
filterTable, err := createTableIfNotExist(n.conn, table.Proto, "filter") filterTable, err := createTableIfNotExist(n.conn, table.Proto, "filter")
if err != nil { if err != nil {
return fmt.Errorf("error ensuring filter table: %w", err) return fmt.Errorf("error ensuring filter table: %w", err)
@ -786,17 +795,23 @@ func insertLoopbackRule(
// getNFTByAddr returns the nftables with correct IP family // getNFTByAddr returns the nftables with correct IP family
// that we will be using for the given address. // that we will be using for the given address.
func (n *nftablesRunner) getNFTByAddr(addr netip.Addr) *nftable { func (n *nftablesRunner) getNFTByAddr(addr netip.Addr) (*nftable, error) {
if addr.Is6() && !n.v6Available {
return nil, fmt.Errorf("nftables for IPv6 are not available on this host")
}
if addr.Is6() { if addr.Is6() {
return n.nft6 return n.nft6, nil
} }
return n.nft4 return n.nft4, nil
} }
// AddLoopbackRule adds an nftables rule to permit loopback traffic to // AddLoopbackRule adds an nftables rule to permit loopback traffic to
// a local Tailscale IP. This rule is added only if it does not already exist. // a local Tailscale IP. This rule is added only if it does not already exist.
func (n *nftablesRunner) AddLoopbackRule(addr netip.Addr) error { func (n *nftablesRunner) AddLoopbackRule(addr netip.Addr) error {
nf := n.getNFTByAddr(addr) nf, err := n.getNFTByAddr(addr)
if err != nil {
return fmt.Errorf("error setting up nftables for IP family of %v: %w", addr, err)
}
inputChain, err := getChainFromTable(n.conn, nf.Filter, chainNameInput) inputChain, err := getChainFromTable(n.conn, nf.Filter, chainNameInput)
if err != nil { if err != nil {
@ -813,7 +828,10 @@ func (n *nftablesRunner) AddLoopbackRule(addr netip.Addr) error {
// DelLoopbackRule removes the nftables rule permitting loopback // DelLoopbackRule removes the nftables rule permitting loopback
// traffic to a Tailscale IP. // traffic to a Tailscale IP.
func (n *nftablesRunner) DelLoopbackRule(addr netip.Addr) error { func (n *nftablesRunner) DelLoopbackRule(addr netip.Addr) error {
nf := n.getNFTByAddr(addr) nf, err := n.getNFTByAddr(addr)
if err != nil {
return fmt.Errorf("error setting up nftables for IP family of %v: %w", addr, err)
}
inputChain, err := getChainFromTable(n.conn, nf.Filter, chainNameInput) inputChain, err := getChainFromTable(n.conn, nf.Filter, chainNameInput)
if err != nil { if err != nil {

Loading…
Cancel
Save