Refactor: remove unused chain-related implementations from the firewall package
This commit is contained in:
@@ -1,41 +0,0 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
nftChain "git.kor-elf.net/kor-elf-shield/go-nftables-client/chain"
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
)
|
||||
|
||||
type AfterLocalInput interface {
|
||||
AddRule(expr ...string) error
|
||||
AddRuleIn(AddRuleFunc func(expr ...string) error) error
|
||||
}
|
||||
|
||||
type afterLocalInput struct {
|
||||
nft nft.NFT
|
||||
family family.Type
|
||||
table string
|
||||
chain string
|
||||
}
|
||||
|
||||
func newAfterLocalInput(nft nft.NFT, family family.Type, table string) (LocalInput, error) {
|
||||
chain := "after-local-input"
|
||||
if err := nft.Chain().Add(family, table, chain, nftChain.TypeNone); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &afterLocalInput{
|
||||
nft: nft,
|
||||
family: family,
|
||||
table: table,
|
||||
chain: chain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *afterLocalInput) AddRule(expr ...string) error {
|
||||
return l.nft.Rule().Add(l.family, l.table, l.chain, expr...)
|
||||
}
|
||||
|
||||
func (l *afterLocalInput) AddRuleIn(AddRuleFunc func(expr ...string) error) error {
|
||||
return AddRuleFunc("iifname != \"lo\" counter jump " + l.chain)
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
nftChain "git.kor-elf.net/kor-elf-shield/go-nftables-client/chain"
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
)
|
||||
|
||||
type BeforeLocalInput interface {
|
||||
AddRule(expr ...string) error
|
||||
AddRuleIn(AddRuleFunc func(expr ...string) error) error
|
||||
}
|
||||
|
||||
type beforeLocalInput struct {
|
||||
nft nft.NFT
|
||||
family family.Type
|
||||
table string
|
||||
chain string
|
||||
}
|
||||
|
||||
func newBeforeLocalInput(nft nft.NFT, family family.Type, table string) (LocalInput, error) {
|
||||
chain := "before-local-input"
|
||||
if err := nft.Chain().Add(family, table, chain, nftChain.TypeNone); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &beforeLocalInput{
|
||||
nft: nft,
|
||||
family: family,
|
||||
table: table,
|
||||
chain: chain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *beforeLocalInput) AddRule(expr ...string) error {
|
||||
return l.nft.Rule().Add(l.family, l.table, l.chain, expr...)
|
||||
}
|
||||
|
||||
func (l *beforeLocalInput) AddRuleIn(AddRuleFunc func(expr ...string) error) error {
|
||||
return AddRuleFunc("iifname != \"lo\" counter jump " + l.chain)
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package block
|
||||
|
||||
import (
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
)
|
||||
|
||||
type Blocklist interface {
|
||||
// ReplaceElementsIPv4 Replacing IP addresses.
|
||||
ReplaceElementsIPv4(ips []string) error
|
||||
|
||||
// ReplaceElementsIPv6 Replacing IP addresses.
|
||||
ReplaceElementsIPv6(ips []string) error
|
||||
|
||||
// AddRuleToChain Add a rule to the parent chain.
|
||||
AddRuleToChain(chainAddRuleFunc func(expr ...string) error, action string) error
|
||||
}
|
||||
|
||||
type blocklist struct {
|
||||
listIPv4 List
|
||||
listIPv6 List
|
||||
}
|
||||
|
||||
func NewBlocklist(nft nft.NFT, family family.Type, table string, name string) (Blocklist, error) {
|
||||
params := "type ipv4_addr; flags interval; auto-merge;"
|
||||
listName := name + "_ip4"
|
||||
listIPv4, err := newList(nft, family, table, listName, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params = "type ipv6_addr; flags interval; auto-merge;"
|
||||
listName = name + "_ip6"
|
||||
listIPv6, err := newList(nft, family, table, listName, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &blocklist{
|
||||
listIPv4: listIPv4,
|
||||
listIPv6: listIPv6,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *blocklist) ReplaceElementsIPv4(ips []string) error {
|
||||
return l.listIPv4.ReplaceElements(ips)
|
||||
}
|
||||
|
||||
func (l *blocklist) ReplaceElementsIPv6(ips []string) error {
|
||||
return l.listIPv6.ReplaceElements(ips)
|
||||
}
|
||||
|
||||
func (l *blocklist) AddRuleToChain(chainAddRuleFunc func(expr ...string) error, action string) error {
|
||||
rule := "ip saddr @" + l.listIPv4.Name() + " " + action
|
||||
if err := chainAddRuleFunc(rule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rule = "ip6 saddr @" + l.listIPv6.Name() + " " + action
|
||||
if err := chainAddRuleFunc(rule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
package block
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
)
|
||||
|
||||
type List interface {
|
||||
Name() string
|
||||
AddElement(element string) error
|
||||
DeleteElement(element string) error
|
||||
ReplaceElements(elements []string) error
|
||||
}
|
||||
|
||||
type list struct {
|
||||
nft nft.NFT
|
||||
family family.Type
|
||||
table string
|
||||
name string
|
||||
}
|
||||
|
||||
func newList(nft nft.NFT, family family.Type, table string, name string, params string) (List, error) {
|
||||
command := []string{
|
||||
"add set", family.String(), table, name, "{ " + params + " }",
|
||||
}
|
||||
if err := nft.Command().Run(command...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &list{
|
||||
nft: nft,
|
||||
family: family,
|
||||
table: table,
|
||||
name: name,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *list) Name() string {
|
||||
return l.name
|
||||
}
|
||||
|
||||
func (l *list) AddElement(element string) error {
|
||||
command := []string{
|
||||
"add element",
|
||||
l.family.String(), l.table, l.name,
|
||||
fmt.Sprintf("{ %s }", element),
|
||||
}
|
||||
return l.nft.Command().Run(command...)
|
||||
}
|
||||
|
||||
func (l *list) DeleteElement(element string) error {
|
||||
command := []string{
|
||||
"delete element",
|
||||
l.family.String(), l.table, l.name,
|
||||
fmt.Sprintf("{ %s }", element),
|
||||
}
|
||||
return l.nft.Command().Run(command...)
|
||||
}
|
||||
|
||||
func (l *list) ReplaceElements(elements []string) error {
|
||||
if len(elements) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := l.nft.Command().Run("flush set", l.family.String(), l.table, l.name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
const batchSize = 200
|
||||
for _, batch := range chunkStrings(elements, batchSize) {
|
||||
command := []string{
|
||||
"add element",
|
||||
l.family.String(), l.table, l.name,
|
||||
fmt.Sprintf("{ %s }", strings.Join(batch, ",")),
|
||||
}
|
||||
if err := l.nft.Command().Run(command...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func chunkStrings(items []string, size int) [][]string {
|
||||
if size <= 0 {
|
||||
size = 100
|
||||
}
|
||||
|
||||
chunks := make([][]string, 0, (len(items)+size-1)/size)
|
||||
for start := 0; start < len(items); start += size {
|
||||
end := start + size
|
||||
if end > len(items) {
|
||||
end = len(items)
|
||||
}
|
||||
chunks = append(chunks, items[start:end])
|
||||
}
|
||||
return chunks
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package block
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
)
|
||||
|
||||
type ListIP interface {
|
||||
// AddIP Add an IP address to the list.
|
||||
AddIP(addr net.IP, banSeconds uint32) error
|
||||
|
||||
// DeleteIP Delete an IP address from the list.
|
||||
DeleteIP(addr net.IP) error
|
||||
|
||||
// AddRuleToChain Add a rule to the parent chain.
|
||||
AddRuleToChain(chainAddRuleFunc func(expr ...string) error, action string) error
|
||||
}
|
||||
|
||||
type listIP struct {
|
||||
listIPv4 List
|
||||
listIPv6 List
|
||||
}
|
||||
|
||||
func NewListIP(nft nft.NFT, family family.Type, table string, name string) (ListIP, error) {
|
||||
params := "type ipv4_addr; flags interval, timeout;"
|
||||
listName := name + "_ip4"
|
||||
listIPv4, err := newList(nft, family, table, listName, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params = "type ipv6_addr; flags interval, timeout;"
|
||||
listName = name + "_ip6"
|
||||
listIPv6, err := newList(nft, family, table, listName, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &listIP{
|
||||
listIPv4: listIPv4,
|
||||
listIPv6: listIPv6,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *listIP) AddIP(addr net.IP, banSeconds uint32) error {
|
||||
el := []string{addr.String()}
|
||||
if banSeconds > 0 {
|
||||
el = append(el, "timeout", fmt.Sprintf("%ds", banSeconds))
|
||||
}
|
||||
|
||||
element := strings.Join(el, " ")
|
||||
|
||||
if addr.To4() != nil {
|
||||
return l.listIPv4.AddElement(element)
|
||||
}
|
||||
|
||||
return l.listIPv6.AddElement(element)
|
||||
}
|
||||
|
||||
func (l *listIP) DeleteIP(addr net.IP) error {
|
||||
if addr == nil {
|
||||
return fmt.Errorf("IP address cannot be nil")
|
||||
}
|
||||
if addr.To4() != nil {
|
||||
return l.listIPv4.DeleteElement(addr.String())
|
||||
}
|
||||
|
||||
return l.listIPv6.DeleteElement(addr.String())
|
||||
}
|
||||
|
||||
func (l *listIP) AddRuleToChain(chainAddRuleFunc func(expr ...string) error, action string) error {
|
||||
rule := "ip saddr @" + l.listIPv4.Name() + " " + action
|
||||
if err := chainAddRuleFunc(rule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rule = "ip6 saddr @" + l.listIPv6.Name() + " " + action
|
||||
if err := chainAddRuleFunc(rule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package block
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/daemon/firewall/types"
|
||||
)
|
||||
|
||||
type ListIPWithPort interface {
|
||||
// AddIP Add an IP address to the list.
|
||||
AddIP(addr net.IP, ports []types.L4Port, banSeconds uint32) error
|
||||
|
||||
// DeleteIP Delete an IP address from the list.
|
||||
DeleteIP(addr net.IP, port types.L4Port) error
|
||||
|
||||
// AddRuleToChain Add a rule to the parent chain.
|
||||
AddRuleToChain(chainAddRuleFunc func(expr ...string) error, action string) error
|
||||
}
|
||||
|
||||
type listIPWithPort struct {
|
||||
listIPv4 List
|
||||
listIPv6 List
|
||||
}
|
||||
|
||||
func NewListIPWithPort(nft nft.NFT, family family.Type, table string, name string) (ListIPWithPort, error) {
|
||||
params := "type ipv4_addr . inet_proto . inet_service; flags interval, timeout;"
|
||||
listName := name + "_ip4"
|
||||
listIPv4, err := newList(nft, family, table, listName, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params = "type ipv6_addr . inet_proto . inet_service; flags interval, timeout;"
|
||||
listName = name + "_ip6"
|
||||
listIPv6, err := newList(nft, family, table, listName, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &listIPWithPort{
|
||||
listIPv4: listIPv4,
|
||||
listIPv6: listIPv6,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *listIPWithPort) AddIP(addr net.IP, ports []types.L4Port, banSeconds uint32) error {
|
||||
if len(ports) == 0 {
|
||||
return fmt.Errorf("ports is empty")
|
||||
}
|
||||
|
||||
var elements []string
|
||||
for _, port := range ports {
|
||||
el := []string{fmt.Sprintf("%s . %s . %d", addr.String(), port.ProtocolString(), port.Number())}
|
||||
if banSeconds > 0 {
|
||||
el = append(el, "timeout", fmt.Sprintf("%ds", banSeconds))
|
||||
}
|
||||
|
||||
elements = append(elements, strings.Join(el, " "))
|
||||
}
|
||||
|
||||
element := strings.Join(elements, ",")
|
||||
if addr.To4() != nil {
|
||||
return l.listIPv4.AddElement(element)
|
||||
}
|
||||
|
||||
return l.listIPv6.AddElement(element)
|
||||
}
|
||||
|
||||
func (l *listIPWithPort) DeleteIP(addr net.IP, port types.L4Port) error {
|
||||
if addr == nil {
|
||||
return fmt.Errorf("IP address cannot be nil")
|
||||
}
|
||||
if port.ToString() == "" {
|
||||
return fmt.Errorf("port cannot be empty")
|
||||
}
|
||||
|
||||
element := fmt.Sprintf("%s . %s . %d", addr.String(), port.ProtocolString(), port.Number())
|
||||
|
||||
if addr.To4() != nil {
|
||||
return l.listIPv4.DeleteElement(element)
|
||||
}
|
||||
|
||||
return l.listIPv6.DeleteElement(element)
|
||||
}
|
||||
|
||||
func (l *listIPWithPort) AddRuleToChain(chainAddRuleFunc func(expr ...string) error, action string) error {
|
||||
rule := "ip saddr . meta l4proto . th dport @" + l.listIPv4.Name() + " " + action
|
||||
if err := chainAddRuleFunc(rule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rule = "ip6 saddr . meta l4proto . th dport @" + l.listIPv6.Name() + " " + action
|
||||
if err := chainAddRuleFunc(rule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package block
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/pkg/ip"
|
||||
)
|
||||
|
||||
func NewPortKnocking(nft nft.NFT, family family.Type, table string, name string, ipVersion ip.Version, timeout uint32) error {
|
||||
params := []string{"type", ipVersion.ToNftForSet() + ";", "flags timeout; timeout", strconv.Itoa(int(timeout)) + "s;"}
|
||||
_, err := newList(nft, family, table, name, strings.Join(params, " "))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
)
|
||||
|
||||
type Chain interface {
|
||||
AddRule(expr ...string) error
|
||||
ListRules() ([]Rule, error)
|
||||
RemoveRuleByHandle(handle uint64) error
|
||||
Clear() error
|
||||
}
|
||||
|
||||
type chain struct {
|
||||
nft nft.NFT
|
||||
family family.Type
|
||||
table string
|
||||
chain string
|
||||
}
|
||||
|
||||
type NftOutput struct {
|
||||
Nftables []NftElement `json:"nftables"`
|
||||
}
|
||||
type NftElement struct {
|
||||
Rule *Rule `json:"rule,omitempty"`
|
||||
}
|
||||
|
||||
type Rule struct {
|
||||
Handle uint64 `json:"handle"`
|
||||
Comment string `json:"comment"`
|
||||
}
|
||||
|
||||
func (c *chain) AddRule(expr ...string) error {
|
||||
return c.nft.Rule().Add(c.family, c.table, c.chain, expr...)
|
||||
}
|
||||
|
||||
func (c *chain) ListRules() ([]Rule, error) {
|
||||
args := []string{"-a", "-j", "list", "chain", c.family.String(), c.table, c.chain}
|
||||
jsonData, err := c.nft.Command().RunWithOutput(args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var output NftOutput
|
||||
if err := json.Unmarshal([]byte(jsonData), &output); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var rules []Rule
|
||||
for _, el := range output.Nftables {
|
||||
if el.Rule != nil {
|
||||
rules = append(rules, *el.Rule)
|
||||
}
|
||||
}
|
||||
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func (c *chain) RemoveRuleByHandle(handle uint64) error {
|
||||
return c.nft.Rule().Delete(c.family, c.table, c.chain, handle)
|
||||
}
|
||||
|
||||
func (c *chain) Clear() error {
|
||||
return c.nft.Chain().Clear(c.family, c.table, c.chain)
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
nftChain "git.kor-elf.net/kor-elf-shield/go-nftables-client/chain"
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
nftFamily "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"
|
||||
)
|
||||
|
||||
type Chains interface {
|
||||
NewPacketFilter(enable bool) error
|
||||
PacketFilter() PacketFilter
|
||||
|
||||
NewInput(chain string, defaultAllow bool, priority int) error
|
||||
Input() Input
|
||||
|
||||
NewOutput(chain string, defaultAllow bool, priority int) error
|
||||
Output() Output
|
||||
|
||||
NewForward(chain string, defaultAllow bool, priority int) error
|
||||
Forward() Forward
|
||||
|
||||
NewBeforeLocalInput() error
|
||||
BeforeLocalInput() BeforeLocalInput
|
||||
|
||||
NewLocalInput() error
|
||||
LocalInput() LocalInput
|
||||
|
||||
NewAfterLocalInput() error
|
||||
AfterLocalInput() AfterLocalInput
|
||||
|
||||
NewLocalOutput() error
|
||||
LocalOutput() LocalOutput
|
||||
|
||||
NewLocalForward() error
|
||||
LocalForward() LocalForward
|
||||
|
||||
ClearRules() error
|
||||
|
||||
NewNoneChain(chain string) (Chain, error)
|
||||
NewChain(chain string, baseChain nftChain.ChainOptions) (Chain, error)
|
||||
NewBlockListIP(name string) (block.ListIP, error)
|
||||
NewBlockListIPWithPort(name string) (block.ListIPWithPort, error)
|
||||
NewBlocklist(name string) (block.Blocklist, error)
|
||||
NewPortKnocking(name string) (PortKnocking, error)
|
||||
}
|
||||
|
||||
type chains struct {
|
||||
input Input
|
||||
output Output
|
||||
forward Forward
|
||||
packetFilter PacketFilter
|
||||
|
||||
beforeLocalInput BeforeLocalInput
|
||||
localInput LocalInput
|
||||
afterLocalInput AfterLocalInput
|
||||
|
||||
localOutput LocalOutput
|
||||
localForward LocalForward
|
||||
|
||||
family nftFamily.Type
|
||||
table string
|
||||
nft nft.NFT
|
||||
}
|
||||
|
||||
func NewChains(nft nft.NFT, table string) (Chains, error) {
|
||||
family := nftFamily.INET
|
||||
|
||||
if err := clearRules(nft, family, table); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := nft.Table().Add(family, table); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &chains{
|
||||
nft: nft,
|
||||
table: table,
|
||||
family: family,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *chains) NewPacketFilter(enable bool) error {
|
||||
filter, err := newPacketFilter(c.nft, c.family, c.table, enable)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.packetFilter = filter
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *chains) PacketFilter() PacketFilter {
|
||||
return c.packetFilter
|
||||
}
|
||||
|
||||
func (c *chains) NewInput(chain string, defaultAllow bool, priority int) error {
|
||||
input, err := newInput(c.nft, c.family, c.table, chain, defaultAllow, priority)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.input = input
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *chains) Input() Input {
|
||||
return c.input
|
||||
}
|
||||
|
||||
func (c *chains) NewOutput(chain string, defaultAllow bool, priority int) error {
|
||||
output, err := newOutput(c.nft, c.family, c.table, chain, defaultAllow, priority)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.output = output
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *chains) Output() Output {
|
||||
return c.output
|
||||
}
|
||||
|
||||
func (c *chains) NewForward(chain string, defaultAllow bool, priority int) error {
|
||||
forward, err := newForward(c.nft, c.family, c.table, chain, defaultAllow, priority)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.forward = forward
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *chains) Forward() Forward {
|
||||
return c.forward
|
||||
}
|
||||
|
||||
func (c *chains) NewBeforeLocalInput() error {
|
||||
newChain, err := newBeforeLocalInput(c.nft, c.family, c.table)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.beforeLocalInput = newChain
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *chains) BeforeLocalInput() BeforeLocalInput {
|
||||
return c.beforeLocalInput
|
||||
}
|
||||
|
||||
func (c *chains) NewLocalInput() error {
|
||||
localInput, err := newLocalInput(c.nft, c.family, c.table)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.localInput = localInput
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *chains) LocalInput() LocalInput {
|
||||
return c.localInput
|
||||
}
|
||||
|
||||
func (c *chains) NewAfterLocalInput() error {
|
||||
newChain, err := newAfterLocalInput(c.nft, c.family, c.table)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.afterLocalInput = newChain
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *chains) AfterLocalInput() AfterLocalInput {
|
||||
return c.afterLocalInput
|
||||
}
|
||||
|
||||
func (c *chains) NewLocalOutput() error {
|
||||
localOutput, err := newLocalOutput(c.nft, c.family, c.table)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.localOutput = localOutput
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *chains) LocalOutput() LocalOutput {
|
||||
return c.localOutput
|
||||
}
|
||||
|
||||
func (c *chains) NewLocalForward() error {
|
||||
localForward, err := newLocalForward(c.nft, c.family, c.table)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.localForward = localForward
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *chains) LocalForward() LocalForward {
|
||||
return c.localForward
|
||||
}
|
||||
|
||||
func (c *chains) ClearRules() error {
|
||||
return clearRules(c.nft, c.family, c.table)
|
||||
}
|
||||
|
||||
func (c *chains) NewNoneChain(chainName string) (Chain, error) {
|
||||
return c.NewChain(chainName, nftChain.TypeNone)
|
||||
}
|
||||
|
||||
func (c *chains) NewChain(chainName string, baseChain nftChain.ChainOptions) (Chain, error) {
|
||||
if err := c.nft.Chain().Add(c.family, c.table, chainName, baseChain); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &chain{
|
||||
nft: c.nft,
|
||||
family: c.family,
|
||||
table: c.table,
|
||||
chain: chainName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *chains) NewBlockListIP(name string) (block.ListIP, error) {
|
||||
blockList, err := block.NewListIP(c.nft, c.family, c.table, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return blockList, nil
|
||||
}
|
||||
|
||||
func (c *chains) NewBlockListIPWithPort(name string) (block.ListIPWithPort, error) {
|
||||
blockList, err := block.NewListIPWithPort(c.nft, c.family, c.table, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return blockList, nil
|
||||
}
|
||||
|
||||
func (c *chains) NewBlocklist(name string) (block.Blocklist, error) {
|
||||
blockList, err := block.NewBlocklist(c.nft, c.family, c.table, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := blockList.AddRuleToChain(c.afterLocalInput.AddRule, "drop"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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 {
|
||||
if err := nft.Table().Delete(family, table); err != nil {
|
||||
if !strings.Contains(string(err.Error()), "delete table "+family.String()+" "+table) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
nftChain "git.kor-elf.net/kor-elf-shield/go-nftables-client/chain"
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
)
|
||||
|
||||
type Forward interface {
|
||||
AddRule(expr ...string) error
|
||||
}
|
||||
|
||||
type forward struct {
|
||||
nft nft.NFT
|
||||
family family.Type
|
||||
table string
|
||||
chain string
|
||||
}
|
||||
|
||||
func newForward(nft nft.NFT, family family.Type, table string, chain string, defaultAllow bool, priority int) (Forward, error) {
|
||||
policy := nftChain.PolicyDrop
|
||||
if defaultAllow {
|
||||
policy = nftChain.PolicyAccept
|
||||
}
|
||||
|
||||
baseChain := nftChain.BaseChainOptions{
|
||||
Type: nftChain.TypeFilter,
|
||||
Hook: nftChain.HookForward,
|
||||
Priority: int32(priority),
|
||||
Policy: policy,
|
||||
Device: "",
|
||||
}
|
||||
|
||||
if err := nft.Chain().Add(family, table, chain, baseChain); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &forward{
|
||||
nft: nft,
|
||||
family: family,
|
||||
table: table,
|
||||
chain: chain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *forward) AddRule(expr ...string) error {
|
||||
return c.nft.Rule().Add(c.family, c.table, c.chain, expr...)
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
nftChain "git.kor-elf.net/kor-elf-shield/go-nftables-client/chain"
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
)
|
||||
|
||||
type Input interface {
|
||||
AddRule(expr ...string) error
|
||||
}
|
||||
|
||||
type input struct {
|
||||
nft nft.NFT
|
||||
family family.Type
|
||||
table string
|
||||
chain string
|
||||
}
|
||||
|
||||
func newInput(nft nft.NFT, family family.Type, table string, chain string, defaultAllow bool, priority int) (Input, error) {
|
||||
policy := nftChain.PolicyDrop
|
||||
if defaultAllow {
|
||||
policy = nftChain.PolicyAccept
|
||||
}
|
||||
|
||||
baseChain := nftChain.BaseChainOptions{
|
||||
Type: nftChain.TypeFilter,
|
||||
Hook: nftChain.HookInput,
|
||||
Priority: int32(priority),
|
||||
Policy: policy,
|
||||
Device: "",
|
||||
}
|
||||
|
||||
if err := nft.Chain().Add(family, table, chain, baseChain); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &input{
|
||||
nft: nft,
|
||||
family: family,
|
||||
table: table,
|
||||
chain: chain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *input) AddRule(expr ...string) error {
|
||||
return c.nft.Rule().Add(c.family, c.table, c.chain, expr...)
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
nftChain "git.kor-elf.net/kor-elf-shield/go-nftables-client/chain"
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
)
|
||||
|
||||
type LocalForward interface {
|
||||
AddRule(expr ...string) error
|
||||
AddRuleIn(AddRuleFunc func(expr ...string) error) error
|
||||
}
|
||||
|
||||
type localForward struct {
|
||||
nft nft.NFT
|
||||
family family.Type
|
||||
table string
|
||||
chain string
|
||||
}
|
||||
|
||||
func newLocalForward(nft nft.NFT, family family.Type, table string) (LocalForward, error) {
|
||||
chain := "local-forward"
|
||||
if err := nft.Chain().Add(family, table, chain, nftChain.TypeNone); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &localForward{
|
||||
nft: nft,
|
||||
family: family,
|
||||
table: table,
|
||||
chain: chain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *localForward) AddRule(expr ...string) error {
|
||||
return l.nft.Rule().Add(l.family, l.table, l.chain, expr...)
|
||||
}
|
||||
|
||||
func (l *localForward) AddRuleIn(AddRuleFunc func(expr ...string) error) error {
|
||||
return AddRuleFunc("iifname != \"lo\" counter jump " + l.chain)
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
nftChain "git.kor-elf.net/kor-elf-shield/go-nftables-client/chain"
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
)
|
||||
|
||||
type LocalInput interface {
|
||||
AddRule(expr ...string) error
|
||||
AddRuleIn(AddRuleFunc func(expr ...string) error) error
|
||||
}
|
||||
|
||||
type localInput struct {
|
||||
nft nft.NFT
|
||||
family family.Type
|
||||
table string
|
||||
chain string
|
||||
}
|
||||
|
||||
func newLocalInput(nft nft.NFT, family family.Type, table string) (LocalInput, error) {
|
||||
chain := "local-input"
|
||||
if err := nft.Chain().Add(family, table, chain, nftChain.TypeNone); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &localInput{
|
||||
nft: nft,
|
||||
family: family,
|
||||
table: table,
|
||||
chain: chain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *localInput) AddRule(expr ...string) error {
|
||||
return l.nft.Rule().Add(l.family, l.table, l.chain, expr...)
|
||||
}
|
||||
|
||||
func (l *localInput) AddRuleIn(AddRuleFunc func(expr ...string) error) error {
|
||||
return AddRuleFunc("iifname != \"lo\" counter jump " + l.chain)
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
nftChain "git.kor-elf.net/kor-elf-shield/go-nftables-client/chain"
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
)
|
||||
|
||||
type LocalOutput interface {
|
||||
AddRule(expr ...string) error
|
||||
AddRuleOut(AddRuleFunc func(expr ...string) error) error
|
||||
}
|
||||
|
||||
type localOutput struct {
|
||||
nft nft.NFT
|
||||
family family.Type
|
||||
table string
|
||||
chain string
|
||||
}
|
||||
|
||||
func newLocalOutput(nft nft.NFT, family family.Type, table string) (LocalOutput, error) {
|
||||
chain := "local-output"
|
||||
if err := nft.Chain().Add(family, table, chain, nftChain.TypeNone); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &localOutput{
|
||||
nft: nft,
|
||||
family: family,
|
||||
table: table,
|
||||
chain: chain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *localOutput) AddRule(expr ...string) error {
|
||||
return l.nft.Rule().Add(l.family, l.table, l.chain, expr...)
|
||||
}
|
||||
|
||||
func (l *localOutput) AddRuleOut(AddRuleFunc func(expr ...string) error) error {
|
||||
return AddRuleFunc("oifname != \"lo\" counter jump " + l.chain)
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
nftChain "git.kor-elf.net/kor-elf-shield/go-nftables-client/chain"
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
)
|
||||
|
||||
type Output interface {
|
||||
AddRule(expr ...string) error
|
||||
}
|
||||
|
||||
type output struct {
|
||||
nft nft.NFT
|
||||
family family.Type
|
||||
table string
|
||||
chain string
|
||||
}
|
||||
|
||||
func newOutput(nft nft.NFT, family family.Type, table string, chain string, defaultAllow bool, priority int) (Output, error) {
|
||||
policy := nftChain.PolicyDrop
|
||||
if defaultAllow {
|
||||
policy = nftChain.PolicyAccept
|
||||
}
|
||||
|
||||
baseChain := nftChain.BaseChainOptions{
|
||||
Type: nftChain.TypeFilter,
|
||||
Hook: nftChain.HookOutput,
|
||||
Priority: int32(priority),
|
||||
Policy: policy,
|
||||
Device: "",
|
||||
}
|
||||
|
||||
if err := nft.Chain().Add(family, table, chain, baseChain); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &output{
|
||||
nft: nft,
|
||||
family: family,
|
||||
table: table,
|
||||
chain: chain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *output) AddRule(expr ...string) error {
|
||||
return c.nft.Rule().Add(c.family, c.table, c.chain, expr...)
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
nftChain "git.kor-elf.net/kor-elf-shield/go-nftables-client/chain"
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
nftFamily "git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
)
|
||||
|
||||
type PacketFilter interface {
|
||||
AddRuleIn(AddRuleFunc func(expr ...string) error) error
|
||||
AddRuleOut(AddRuleFunc func(expr ...string) error) error
|
||||
}
|
||||
|
||||
type packetFilter struct {
|
||||
enable bool
|
||||
invalidName string
|
||||
}
|
||||
|
||||
// newPacketFilter Drop out of order packets and packets in an INVALID state in nftables connection tracking.
|
||||
func newPacketFilter(nft nft.NFT, family nftFamily.Type, table string, enable bool) (PacketFilter, error) {
|
||||
chainInvalidName := "INVALID"
|
||||
if !enable {
|
||||
return &packetFilter{
|
||||
enable: enable,
|
||||
invalidName: chainInvalidName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
chainName := "INVDROP"
|
||||
|
||||
if err := nft.Chain().Add(family, table, chainName, nftChain.TypeNone); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := nft.Rule().Add(family, table, chainName, "counter drop"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := nft.Chain().Add(family, table, chainInvalidName, nftChain.TypeNone); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := nft.Rule().Add(family, table, chainInvalidName, "ct state invalid counter jump INVDROP"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := nft.Rule().Add(family, table, chainInvalidName, "tcp flags ! fin,syn,rst,psh,ack,urg counter jump INVDROP"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := nft.Rule().Add(family, table, chainInvalidName, "tcp flags & (fin | syn | rst | psh | ack | urg) == fin | syn | rst | psh | ack | urg counter jump INVDROP"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := nft.Rule().Add(family, table, chainInvalidName, "tcp flags & (fin | syn) == fin | syn counter jump INVDROP"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := nft.Rule().Add(family, table, chainInvalidName, "tcp flags & (syn | rst) == syn | rst counter jump INVDROP"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := nft.Rule().Add(family, table, chainInvalidName, "tcp flags & (fin | rst) == fin | rst counter jump INVDROP"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := nft.Rule().Add(family, table, chainInvalidName, "tcp flags & (fin | ack) == fin counter jump INVDROP"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := nft.Rule().Add(family, table, chainInvalidName, "tcp flags & (psh | ack) == psh counter jump INVDROP"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := nft.Rule().Add(family, table, chainInvalidName, "tcp flags & (ack | urg) == urg counter jump INVDROP"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := nft.Rule().Add(family, table, chainInvalidName, "tcp flags & (fin | syn | rst | ack) != syn ct state new counter jump INVDROP"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &packetFilter{
|
||||
enable: enable,
|
||||
invalidName: chainInvalidName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *packetFilter) AddRuleIn(AddRuleFunc func(expr ...string) error) error {
|
||||
if !f.enable {
|
||||
return nil
|
||||
}
|
||||
return AddRuleFunc("iifname != \"lo\" meta l4proto tcp counter jump " + f.invalidName)
|
||||
}
|
||||
|
||||
func (f *packetFilter) AddRuleOut(AddRuleFunc func(expr ...string) error) error {
|
||||
if !f.enable {
|
||||
return nil
|
||||
}
|
||||
return AddRuleFunc("oifname != \"lo\" meta l4proto tcp counter jump " + f.invalidName)
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
nftChain "git.kor-elf.net/kor-elf-shield/go-nftables-client/chain"
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client/contract"
|
||||
"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...)
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package firewall
|
||||
|
||||
import nftChain "git.kor-elf.net/kor-elf-shield/go-nftables-client/chain"
|
||||
|
||||
func (f *firewall) reloadDocker() error {
|
||||
f.logger.Debug("Reload docker rules")
|
||||
if err := f.reloadDockerPrerouting(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *firewall) reloadDockerPrerouting() error {
|
||||
preroutingNat, err := f.chains.NewChain("prerouting_nat", nftChain.BaseChainOptions{
|
||||
Type: nftChain.TypeNat,
|
||||
Hook: nftChain.HookPrerouting,
|
||||
Priority: -100,
|
||||
Policy: nftChain.PolicyAccept,
|
||||
Device: "",
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := f.docker.NftChains().PreroutingNatJump(preroutingNat.AddRule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
preroutingFilter, err := f.chains.NewChain("prerouting_filter", nftChain.BaseChainOptions{
|
||||
Type: nftChain.TypeFilter,
|
||||
Hook: nftChain.HookPrerouting,
|
||||
Priority: -300,
|
||||
Policy: nftChain.PolicyAccept,
|
||||
Device: "",
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := f.docker.NftChains().PreroutingFilterJump(preroutingFilter.AddRule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
outputNat, err := f.chains.NewChain("output_nat", nftChain.BaseChainOptions{
|
||||
Type: nftChain.TypeNat,
|
||||
Hook: nftChain.HookOutput,
|
||||
Priority: -100,
|
||||
Policy: nftChain.PolicyAccept,
|
||||
Device: "",
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := f.docker.NftChains().OutputNatJump(outputNat.AddRule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
postroutingNat, err := f.chains.NewChain("postrouting_nat", nftChain.BaseChainOptions{
|
||||
Type: nftChain.TypeNat,
|
||||
Hook: nftChain.HookPostrouting,
|
||||
Priority: 300,
|
||||
Policy: nftChain.PolicyAccept,
|
||||
Device: "",
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := f.docker.NftChains().PostroutingNatJump(postroutingNat.AddRule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package firewall
|
||||
|
||||
func (f *firewall) reloadBlockList() error {
|
||||
listBlockedIP, err := f.chains.NewBlockListIP("blocked_ip")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := listBlockedIP.AddRuleToChain(f.chains.BeforeLocalInput().AddRule, "drop"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
listBlockedIPWithPort, err := f.chains.NewBlockListIPWithPort("blocked_ip_port")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := listBlockedIPWithPort.AddRuleToChain(f.chains.BeforeLocalInput().AddRule, "drop"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.blockingService.NftReload(listBlockedIP, listBlockedIPWithPort); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package firewall
|
||||
|
||||
import (
|
||||
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/daemon/firewall/config"
|
||||
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/daemon/firewall/types"
|
||||
)
|
||||
|
||||
func (f *firewall) reloadForward() error {
|
||||
f.logger.Debug("Reloading forward chain")
|
||||
err := f.chains.NewForward(f.config.MetadataNaming.ChainForwardName, f.config.Policy.DefaultAllowForward, f.config.Policy.ForwardPriority)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chain := f.chains.Forward()
|
||||
|
||||
if err := f.reloadForwardAddIPs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if f.config.Options.DockerSupport {
|
||||
if err := f.docker.NftChains().ForwardFilterJump(chain.AddRule); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if f.config.Policy.DefaultAllowForward == false {
|
||||
drop := f.config.Policy.ForwardDrop.String()
|
||||
if err := chain.AddRule(drop); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *firewall) reloadForwardAddIPs() error {
|
||||
if err := f.chains.NewLocalForward(); err != nil {
|
||||
return err
|
||||
}
|
||||
chain := f.chains.LocalForward()
|
||||
if err := chain.AddRuleIn(f.chains.Forward().AddRule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, ipConfig := range f.config.IP4.InIPs {
|
||||
if ipConfig.Action != types.ActionDrop && ipConfig.Action != types.ActionReject {
|
||||
continue
|
||||
}
|
||||
if err := forwardAddIP(chain.AddRule, ipConfig, "ip"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !f.config.IP6.Enable {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, ipConfig := range f.config.IP6.InIPs {
|
||||
if ipConfig.Action != types.ActionDrop && ipConfig.Action != types.ActionReject {
|
||||
continue
|
||||
}
|
||||
if err := forwardAddIP(chain.AddRule, ipConfig, "ip6"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func forwardAddIP(addRuleFunc func(expr ...string) error, config config.ConfigIP, ipMatch string) error {
|
||||
rule := ipMatch + " saddr " + config.IP + " iifname != \"lo\""
|
||||
|
||||
// There, during routing, the port changes and then the IP blocking rule will not work.
|
||||
//if !config.OnlyIP {
|
||||
// rule += " " + config.Protocol.String() + " dport " + strconv.Itoa(int(config.Port))
|
||||
//}
|
||||
|
||||
rule += " counter " + config.Action.String()
|
||||
if err := addRuleFunc(rule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,332 +0,0 @@
|
||||
package firewall
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/daemon/firewall/chain"
|
||||
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/daemon/firewall/config"
|
||||
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/pkg"
|
||||
)
|
||||
|
||||
func (f *firewall) reloadInput() error {
|
||||
f.logger.Debug("Reloading input chain")
|
||||
err := f.chains.NewInput(f.config.MetadataNaming.ChainInputName, f.config.Policy.DefaultAllowInput, f.config.Policy.InputPriority)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chain := f.chains.Input()
|
||||
|
||||
if err := f.reloadInputDnsNs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := chain.AddRule("iifname lo counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.chains.NewBeforeLocalInput(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := f.chains.BeforeLocalInput().AddRuleIn(chain.AddRule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.reloadInputAddIPs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.chains.NewAfterLocalInput(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := f.chains.AfterLocalInput().AddRuleIn(chain.AddRule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.chains.PacketFilter().AddRuleIn(chain.AddRule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.reloadInputICMP(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := chain.AddRule("iifname != \"lo\" ct state related,established counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.reloadInputPorts(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if f.config.Policy.DefaultAllowInput == false {
|
||||
drop := f.config.Policy.InputDrop.String()
|
||||
if err := chain.AddRule("iifname != \"lo\" " + drop); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *firewall) reloadInputDnsNs() error {
|
||||
if f.config.Options.DnsStrictNs {
|
||||
return nil
|
||||
}
|
||||
chain := f.chains.Input()
|
||||
|
||||
addresses, err := pkg.Resolv.Addresses()
|
||||
if err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to get nameservers: %s", err))
|
||||
return nil
|
||||
}
|
||||
for _, addr := range addresses {
|
||||
ip := net.ParseIP(addr)
|
||||
if ip == nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to parse nameserver address: %s", addr))
|
||||
continue
|
||||
}
|
||||
if ip.To4() != nil {
|
||||
if err := chain.AddRule("ip saddr " + addr + " iifname != \"lo\" tcp dport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
if err := chain.AddRule("ip saddr " + addr + " iifname != \"lo\" udp dport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
if err := chain.AddRule("ip saddr " + addr + " iifname != \"lo\" tcp sport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
if err := chain.AddRule("ip saddr " + addr + " iifname != \"lo\" udp sport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if ip.To16() != nil {
|
||||
if !f.config.IP6.Enable {
|
||||
f.logger.Warn(fmt.Sprintf("IPv6 is disabled, skipping nameserver address: %s", addr))
|
||||
continue
|
||||
}
|
||||
if err := chain.AddRule("ip6 saddr " + addr + " iifname != \"lo\" tcp dport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
if err := chain.AddRule("ip6 saddr " + addr + " iifname != \"lo\" udp dport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
if err := chain.AddRule("ip6 saddr " + addr + " iifname != \"lo\" tcp sport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
if err := chain.AddRule("ip6 saddr " + addr + " iifname != \"lo\" udp sport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
f.logger.Error(fmt.Sprintf("Failed to parse nameserver address: %s", addr))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *firewall) reloadInputICMP() error {
|
||||
chain := f.chains.Input()
|
||||
drop := f.config.Policy.InputDrop.String()
|
||||
if f.config.IP4.IcmpIn == false {
|
||||
if err := chain.AddRule("iifname != \"lo\" ip protocol icmp icmp type echo-request counter " + drop); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.reloadInputICMPAfter()
|
||||
}
|
||||
|
||||
if f.config.IP4.IcmpInRate == "0" {
|
||||
return f.reloadInputICMPAfter()
|
||||
}
|
||||
|
||||
if err := chain.AddRule("iifname != \"lo\" ip protocol icmp icmp type echo-request limit rate " + f.config.IP4.IcmpInRate + " counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("iifname != \"lo\" ip protocol icmp icmp type echo-request counter " + drop); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return f.reloadInputICMPAfter()
|
||||
}
|
||||
func (f *firewall) reloadInputICMPAfter() error {
|
||||
chain := f.chains.Input()
|
||||
|
||||
if f.config.IP4.IcmpTimestampDrop == true {
|
||||
drop := f.config.Policy.InputDrop.String()
|
||||
if err := chain.AddRule("iifname != \"lo\" ip protocol icmp icmp type timestamp-request " + drop); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := chain.AddRule("iifname != \"lo\" ip protocol icmp counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if f.config.IP6.Enable {
|
||||
if f.config.IP6.IcmpStrict {
|
||||
return f.reloadInputICMP6Strict()
|
||||
} else {
|
||||
if err := chain.AddRule("iifname != \"lo\" meta l4proto ipv6-icmp counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *firewall) reloadInputICMP6Strict() error {
|
||||
chain := f.chains.Input()
|
||||
if err := chain.AddRule("iifname != \"lo\" meta l4proto ipv6-icmp icmpv6 type destination-unreachable counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("iifname != \"lo\" meta l4proto ipv6-icmp icmpv6 type packet-too-big counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("iifname != \"lo\" meta l4proto ipv6-icmp icmpv6 type time-exceeded counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("iifname != \"lo\" meta l4proto ipv6-icmp icmpv6 type parameter-problem counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("iifname != \"lo\" meta l4proto ipv6-icmp icmpv6 type echo-request counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("iifname != \"lo\" meta l4proto ipv6-icmp icmpv6 type echo-reply counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("iifname != \"lo\" meta l4proto ipv6-icmp icmpv6 type nd-router-advert ip6 hoplimit 255 counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("iifname != \"lo\" meta l4proto ipv6-icmp icmpv6 type nd-neighbor-solicit ip6 hoplimit 255 counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("iifname != \"lo\" meta l4proto ipv6-icmp icmpv6 type nd-neighbor-advert ip6 hoplimit 255 counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("iifname != \"lo\" meta l4proto ipv6-icmp icmpv6 type nd-redirect ip6 hoplimit 255 counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *firewall) reloadInputPorts() error {
|
||||
chain := f.chains.Input()
|
||||
for _, port := range f.config.InPorts {
|
||||
protocol := port.Port.ProtocolString()
|
||||
number := port.Port.NumberString()
|
||||
|
||||
baseRule := "iifname != \"lo\" meta l4proto " + protocol + " ct state new " + protocol + " dport " + number
|
||||
|
||||
if port.LimitRate != "" {
|
||||
rule := baseRule + " limit rate " + port.LimitRate + " counter " + port.Action.String()
|
||||
if err := chain.AddRule(rule); err != nil {
|
||||
return err
|
||||
}
|
||||
ruleDrop := baseRule + " counter " + f.config.Policy.InputDrop.String()
|
||||
if err := chain.AddRule(ruleDrop); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
rule := baseRule + " counter " + port.Action.String()
|
||||
if err := chain.AddRule(rule); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *firewall) reloadInputAddIPs() error {
|
||||
if err := f.chains.NewLocalInput(); err != nil {
|
||||
return err
|
||||
}
|
||||
chain := f.chains.LocalInput()
|
||||
if err := chain.AddRuleIn(f.chains.Input().AddRule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.reloadPortKnocking(chain); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, ipConfig := range f.config.IP4.InIPs {
|
||||
if err := inputAddIP(chain.AddRule, ipConfig, "ip"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !f.config.IP6.Enable {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, ipConfig := range f.config.IP6.InIPs {
|
||||
if err := inputAddIP(chain.AddRule, ipConfig, "ip6"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *firewall) reloadPortKnocking(chain chain.LocalInput) error {
|
||||
if len(f.config.PortKnocking) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
portKnocking, err := f.chains.NewPortKnocking("port_knocking")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, portKnockingConfig := range f.config.PortKnocking {
|
||||
var knockName, prevKnockName string
|
||||
for index, knock := range portKnockingConfig.Knocks {
|
||||
prevKnockName = knockName
|
||||
knockName = fmt.Sprintf("knock_%s_%d", portKnockingConfig.Name, index)
|
||||
if index == 0 {
|
||||
if err := portKnocking.AddFirstStageRule(knockName, portKnockingConfig.IPVersion, knock.Port, knock.Timeout, knock.Action); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if err := portKnocking.AddNextStageRule(prevKnockName, knockName, portKnockingConfig.IPVersion, knock.Port, knock.Timeout, knock.Action); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
expr := []string{
|
||||
portKnockingConfig.IPVersion.ToNft(), "saddr", "@" + knockName,
|
||||
portKnockingConfig.Port.ProtocolString(), "dport", portKnockingConfig.Port.NumberString(), "accept",
|
||||
}
|
||||
if err := chain.AddRule(expr...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := portKnocking.AddRuleIn(chain.AddRule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func inputAddIP(addRuleFunc func(expr ...string) error, config config.ConfigIP, ipMatch string) error {
|
||||
|
||||
rule := ipMatch + " saddr " + config.IP + " iifname != \"lo\""
|
||||
if !config.OnlyIP {
|
||||
rule += " " + config.Port.ProtocolString() + " dport " + config.Port.NumberString()
|
||||
}
|
||||
if config.LimitRate != "" {
|
||||
rule += " limit rate " + config.LimitRate
|
||||
}
|
||||
rule += " counter " + config.Action.String()
|
||||
if err := addRuleFunc(rule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,245 +0,0 @@
|
||||
package firewall
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/daemon/firewall/config"
|
||||
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/pkg"
|
||||
)
|
||||
|
||||
func (f *firewall) reloadOutput() error {
|
||||
f.logger.Debug("Reloading output chain")
|
||||
err := f.chains.NewOutput(f.config.MetadataNaming.ChainOutputName, f.config.Policy.DefaultAllowOutput, f.config.Policy.OutputPriority)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
chain := f.chains.Output()
|
||||
|
||||
if err := f.reloadOutputDnsNs(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := f.reloadOutputDns(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("oifname lo counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.reloadOutputAddIPs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.chains.PacketFilter().AddRuleOut(chain.AddRule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.reloadOutputICMP(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := chain.AddRule("oifname != \"lo\" ct state related,established counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f.reloadOutputPorts(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if f.config.Policy.DefaultAllowOutput == false {
|
||||
drop := f.config.Policy.OutputDrop.String()
|
||||
if err := chain.AddRule("oifname != \"lo\" " + drop); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *firewall) reloadOutputDns() error {
|
||||
if f.config.Options.DnsStrict {
|
||||
return nil
|
||||
}
|
||||
chain := f.chains.Output()
|
||||
|
||||
if err := chain.AddRule("oifname != \"lo\" tcp dport 53 counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("oifname != \"lo\" udp dport 53 counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("oifname != \"lo\" tcp sport 53 counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("oifname != \"lo\" udp sport 53 counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *firewall) reloadOutputDnsNs() error {
|
||||
if f.config.Options.DnsStrictNs {
|
||||
return nil
|
||||
}
|
||||
chain := f.chains.Output()
|
||||
|
||||
addresses, err := pkg.Resolv.Addresses()
|
||||
if err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to get nameservers: %s", err))
|
||||
return nil
|
||||
}
|
||||
for _, addr := range addresses {
|
||||
ip := net.ParseIP(addr)
|
||||
if ip == nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to parse nameserver address: %s", addr))
|
||||
continue
|
||||
}
|
||||
if ip.To4() != nil {
|
||||
if err := chain.AddRule("ip daddr " + addr + " oifname != \"lo\" tcp dport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
if err := chain.AddRule("ip daddr " + addr + " oifname != \"lo\" udp dport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
if err := chain.AddRule("ip daddr " + addr + " oifname != \"lo\" tcp sport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
if err := chain.AddRule("ip daddr " + addr + " oifname != \"lo\" udp sport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if ip.To16() != nil {
|
||||
if err := chain.AddRule("ip6 daddr " + addr + " oifname != \"lo\" tcp dport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
if err := chain.AddRule("ip6 daddr " + addr + " oifname != \"lo\" udp dport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
if err := chain.AddRule("ip6 daddr " + addr + " oifname != \"lo\" tcp sport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
if err := chain.AddRule("ip6 daddr " + addr + " oifname != \"lo\" udp sport 53 counter accept"); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to add rule: %s", err))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
f.logger.Error(fmt.Sprintf("Failed to parse nameserver address: %s", addr))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *firewall) reloadOutputICMP() error {
|
||||
chain := f.chains.Output()
|
||||
drop := f.config.Policy.OutputDrop.String()
|
||||
if f.config.IP4.IcmpOut == false {
|
||||
if err := chain.AddRule("oifname != \"lo\" ip protocol icmp icmp type echo-request counter " + drop); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.reloadOutputICMPAfter()
|
||||
}
|
||||
|
||||
if f.config.IP4.IcmpOutRate == "0" {
|
||||
return f.reloadOutputICMPAfter()
|
||||
}
|
||||
|
||||
if err := chain.AddRule("oifname != \"lo\" ip protocol icmp icmp type echo-request limit rate " + f.config.IP4.IcmpInRate + " counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chain.AddRule("oifname != \"lo\" ip protocol icmp icmp type echo-request counter " + drop); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return f.reloadOutputICMPAfter()
|
||||
}
|
||||
|
||||
func (f *firewall) reloadOutputICMPAfter() error {
|
||||
chain := f.chains.Output()
|
||||
|
||||
if f.config.IP4.IcmpTimestampDrop == true {
|
||||
drop := f.config.Policy.OutputDrop.String()
|
||||
if err := chain.AddRule("oifname != \"lo\" ip protocol icmp icmp type timestamp-request " + drop); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := chain.AddRule("oifname != \"lo\" ip protocol icmp counter accept"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *firewall) reloadOutputPorts() error {
|
||||
chain := f.chains.Output()
|
||||
for _, port := range f.config.OutPorts {
|
||||
protocol := port.Port.ProtocolString()
|
||||
number := port.Port.NumberString()
|
||||
baseRule := "oifname != \"lo\" meta l4proto " + protocol + " ct state new " + protocol + " dport " + number
|
||||
|
||||
if port.LimitRate != "" {
|
||||
rule := baseRule + " limit rate " + port.LimitRate + " counter " + port.Action.String()
|
||||
if err := chain.AddRule(rule); err != nil {
|
||||
return err
|
||||
}
|
||||
ruleDrop := baseRule + " counter " + f.config.Policy.InputDrop.String()
|
||||
if err := chain.AddRule(ruleDrop); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
rule := baseRule + " counter " + port.Action.String()
|
||||
if err := chain.AddRule(rule); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *firewall) reloadOutputAddIPs() error {
|
||||
if err := f.chains.NewLocalOutput(); err != nil {
|
||||
return err
|
||||
}
|
||||
chain := f.chains.LocalOutput()
|
||||
if err := chain.AddRuleOut(f.chains.Output().AddRule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, ipConfig := range f.config.IP4.OutIPs {
|
||||
if err := outputAddIP(chain.AddRule, ipConfig, "ip"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !f.config.IP6.Enable {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, ipConfig := range f.config.IP6.OutIPs {
|
||||
if err := outputAddIP(chain.AddRule, ipConfig, "ip6"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func outputAddIP(addRuleFunc func(expr ...string) error, config config.ConfigIP, ipMatch string) error {
|
||||
|
||||
rule := ipMatch + " daddr " + config.IP + " oifname != \"lo\""
|
||||
if !config.OnlyIP {
|
||||
rule += " " + config.Port.ProtocolString() + " dport " + config.Port.NumberString()
|
||||
}
|
||||
if config.LimitRate != "" {
|
||||
rule += " limit rate " + config.LimitRate
|
||||
}
|
||||
rule += " counter " + config.Action.String()
|
||||
if err := addRuleFunc(rule); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user