Add PortKnocking interface and implementation to manage port-knocking rules and sequences
This commit is contained in:
@@ -44,6 +44,7 @@ type Chains interface {
|
|||||||
NewBlockListIP(name string) (block.ListIP, error)
|
NewBlockListIP(name string) (block.ListIP, error)
|
||||||
NewBlockListIPWithPort(name string) (block.ListIPWithPort, error)
|
NewBlockListIPWithPort(name string) (block.ListIPWithPort, error)
|
||||||
NewBlocklist(name string) (block.Blocklist, error)
|
NewBlocklist(name string) (block.Blocklist, error)
|
||||||
|
NewPortKnocking(name string) (PortKnocking, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type chains struct {
|
type chains struct {
|
||||||
@@ -255,6 +256,15 @@ func (c *chains) NewBlocklist(name string) (block.Blocklist, error) {
|
|||||||
return blockList, nil
|
return blockList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *chains) NewPortKnocking(name string) (PortKnocking, error) {
|
||||||
|
portKnocking, err := newPortKnocking(c.nft, c.family, c.table, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return portKnocking, nil
|
||||||
|
}
|
||||||
|
|
||||||
func clearRules(nft nft.NFT, family nftFamily.Type, table string) error {
|
func clearRules(nft nft.NFT, family nftFamily.Type, table string) error {
|
||||||
if err := nft.Table().Delete(family, table); err != nil {
|
if err := nft.Table().Delete(family, table); err != nil {
|
||||||
if !strings.Contains(string(err.Error()), "delete table "+family.String()+" "+table) {
|
if !strings.Contains(string(err.Error()), "delete table "+family.String()+" "+table) {
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package chain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client"
|
||||||
|
nftChain "git.kor-elf.net/kor-elf-shield/go-nftables-client/chain"
|
||||||
|
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||||
|
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/daemon/firewall/chain/block"
|
||||||
|
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/daemon/firewall/types"
|
||||||
|
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/pkg/ip"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PortKnocking interface {
|
||||||
|
AddFirstStageRule(
|
||||||
|
name string,
|
||||||
|
ipVersion ip.Version,
|
||||||
|
l4Port types.L4Port,
|
||||||
|
timeout uint32,
|
||||||
|
action types.KnockAction,
|
||||||
|
) error
|
||||||
|
AddNextStageRule(
|
||||||
|
prevName, nextName string,
|
||||||
|
ipVersion ip.Version,
|
||||||
|
l4Port types.L4Port,
|
||||||
|
timeout uint32,
|
||||||
|
action types.KnockAction,
|
||||||
|
) error
|
||||||
|
AddRuleIn(AddRuleFunc func(expr ...string) error) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type portKnocking struct {
|
||||||
|
nft nft.NFT
|
||||||
|
family family.Type
|
||||||
|
table string
|
||||||
|
chain string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPortKnocking(nft nft.NFT, family family.Type, table string, chain string) (PortKnocking, error) {
|
||||||
|
if err := nft.Chain().Add(family, table, chain, nftChain.TypeNone); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &portKnocking{
|
||||||
|
nft: nft,
|
||||||
|
family: family,
|
||||||
|
table: table,
|
||||||
|
chain: chain,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *portKnocking) AddRuleIn(AddRuleFunc func(expr ...string) error) error {
|
||||||
|
return AddRuleFunc("iifname != \"lo\" counter jump " + k.chain)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *portKnocking) AddFirstStageRule(
|
||||||
|
name string,
|
||||||
|
ipVersion ip.Version,
|
||||||
|
l4Port types.L4Port,
|
||||||
|
timeout uint32,
|
||||||
|
action types.KnockAction,
|
||||||
|
) error {
|
||||||
|
if err := block.NewPortKnocking(k.nft, k.family, k.table, name, ipVersion, timeout); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
expr := []string{
|
||||||
|
l4Port.ProtocolString(), "dport", l4Port.NumberString(), "add", "@" + name,
|
||||||
|
"{", ipVersion.ToNft(), "saddr timeout", strconv.Itoa(int(timeout)) + "s", "}", action.String(),
|
||||||
|
}
|
||||||
|
return k.nft.Rule().Add(k.family, k.table, k.chain, expr...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *portKnocking) AddNextStageRule(
|
||||||
|
prevName, nextName string,
|
||||||
|
ipVersion ip.Version,
|
||||||
|
l4Port types.L4Port,
|
||||||
|
timeout uint32,
|
||||||
|
action types.KnockAction,
|
||||||
|
) error {
|
||||||
|
if err := block.NewPortKnocking(k.nft, k.family, k.table, nextName, ipVersion, timeout); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
expr := []string{
|
||||||
|
ipVersion.ToNft(), "saddr", "@" + prevName,
|
||||||
|
l4Port.ProtocolString(), "dport", l4Port.NumberString(), "add", "@" + nextName,
|
||||||
|
"{", ipVersion.ToNft(), "saddr}", action.String(),
|
||||||
|
}
|
||||||
|
return k.nft.Rule().Add(k.family, k.table, k.chain, expr...)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user