From f47675e0560ee03409f3ce5a0893bf49bdd9faca Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 11 May 2024 15:37:53 +0200 Subject: [PATCH] bind port mappings to HostIP, if specified (#25) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using `podman run -p 10.25.0.1:8443:8443` before this commit, port 8443 would be reachable on all interfaces, as if one used `podman run -p 8443:8443`. This is obviously not great for security — I’m using podman on an internet router with multiple network interfaces and really want to have my container ports reachable only internally, not also on the public internet :) --- pkg/utils/chain_jump_rule.go | 68 ++++++++++++++++++------------------ pkg/utils/dest_nat.go | 5 +++ 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/pkg/utils/chain_jump_rule.go b/pkg/utils/chain_jump_rule.go index 6001a4e..0e55361 100644 --- a/pkg/utils/chain_jump_rule.go +++ b/pkg/utils/chain_jump_rule.go @@ -83,19 +83,13 @@ func GetJumpRule(v, tableName, srcChainName, dstChainName string) (*nftables.Rul return nil, nil } -// CreateJumpRuleWithIPDaddrMatch creates a jump rule from one chain to -// another that will trigger when the destination IP address is one -// handled by the local system. The resulting rule will be placed in -// and look like -// "ip daddr jump " -func CreateJumpRuleWithIPDaddrMatch(v, tableName, srcChainName, dstChainName string, ipAddress net.IP) error { - - var conditions []expr.Any - +// IPDaddrMatch returns the nftables exprs required for matching the provided +// IPv4 or IPv6 address as destination address. +func IPDaddrMatch(v string, ipAddress net.IP) []expr.Any { if v == "6" { // payload load 4b @ network header + 16 => reg 1 // cmp eq reg 1 0xc8c8a8c0 - conditions = []expr.Any{ + return []expr.Any{ &expr.Payload{ DestRegister: 1, Base: expr.PayloadBaseNetworkHeader, @@ -107,32 +101,38 @@ func CreateJumpRuleWithIPDaddrMatch(v, tableName, srcChainName, dstChainName str Register: 1, Data: ipAddress.To16(), }, - &expr.Verdict{ - Kind: expr.VerdictJump, - Chain: dstChainName, - }, - } - } else { - // payload load 4b @ network header + 16 => reg 1 - // cmp eq reg 1 0x6464a8c0 ] - conditions = []expr.Any{ - &expr.Payload{ - DestRegister: 1, - Base: expr.PayloadBaseNetworkHeader, - Offset: 16, - Len: 4, - }, - &expr.Cmp{ - Op: expr.CmpOpEq, - Register: 1, - Data: ipAddress.To4(), - }, - &expr.Verdict{ - Kind: expr.VerdictJump, - Chain: dstChainName, - }, } } + // payload load 4b @ network header + 16 => reg 1 + // cmp eq reg 1 0x6464a8c0 ] + return []expr.Any{ + &expr.Payload{ + DestRegister: 1, + Base: expr.PayloadBaseNetworkHeader, + Offset: 16, + Len: 4, + }, + &expr.Cmp{ + Op: expr.CmpOpEq, + Register: 1, + Data: ipAddress.To4(), + }, + } +} + +// CreateJumpRuleWithIPDaddrMatch creates a jump rule from one chain to +// another that will trigger when the destination IP address is one +// handled by the local system. The resulting rule will be placed in +// and look like +// "ip daddr jump " +func CreateJumpRuleWithIPDaddrMatch(v, tableName, srcChainName, dstChainName string, ipAddress net.IP) error { + + conditions := IPDaddrMatch(v, ipAddress) + conditions = append(conditions, &expr.Verdict{ + Kind: expr.VerdictJump, + Chain: dstChainName, + }) + return createJumpRule(v, tableName, srcChainName, dstChainName, conditions) } diff --git a/pkg/utils/dest_nat.go b/pkg/utils/dest_nat.go index 45e4018..4bd3fd0 100644 --- a/pkg/utils/dest_nat.go +++ b/pkg/utils/dest_nat.go @@ -62,6 +62,11 @@ func AddDestinationNatRules(opts map[string]interface{}) error { Data: EncodeInterfaceName(bridgeIntfName), }) + // match host IP, if specified + if hostIP := net.ParseIP(pm.HostIP); hostIP != nil { + r.Exprs = append(r.Exprs, IPDaddrMatch(v, hostIP)...) + } + // match port r.Exprs = append(r.Exprs, &expr.Meta{