Merge pull request 'v0.2.0' (#2) from develop into main
Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,3 +1,17 @@
|
||||
## 0.2.0 (29.11.2025)
|
||||
***
|
||||
#### Русский
|
||||
* Добавлен параметр clear_mode в firewall.toml. Он позволяет переключать режим очистки всех правил в nftables или только таблицу относящие к программе.
|
||||
* Добавлен параметр input_priority в firewall.toml. Можно указать приоритет от -50 по 50 к chain input.
|
||||
* Добавлен параметр output_priority в firewall.toml. Можно указать приоритет от -50 по 50 к chain output.
|
||||
* Добавлен параметр forward_priority в firewall.toml. Можно указать приоритет от -50 по 50 к chain forward.
|
||||
***
|
||||
#### English
|
||||
* Added the clear_mode parameter to firewall.toml. It allows you to toggle clearing of all rules in nftables or only the program-specific table.
|
||||
* Added the input_priority parameter to firewall.toml. You can specify a priority from -50 to 50 for chain input.
|
||||
* Added the output_priority parameter to firewall.toml. You can specify a priority from -50 to 50 for chain output.
|
||||
* Added the forward_priority parameter to firewall.toml. You can specify a priority from -50 to 50 for chain forward.
|
||||
***
|
||||
## 0.1.0 (8.11.2025)
|
||||
***
|
||||
#### Русский
|
||||
|
||||
@@ -299,6 +299,26 @@ icmp_strict = false
|
||||
# SECTION:General Settings
|
||||
###############################################################################
|
||||
[options]
|
||||
|
||||
###
|
||||
# Переключения режима очистки фаервола nftables. Если указать "own", то может получиться конфликт в правилах.
|
||||
# Может спровоцировать проблему в безопасности. Указывайте "own" если вы уверены в своих действиях.
|
||||
# Допустимые значения:
|
||||
# global = очищает полностью все правила
|
||||
# own = очищает только правила от таблицы, которые указаны в параметре table_name
|
||||
#
|
||||
# По умолчанию: global
|
||||
# ***
|
||||
# Switching the nftables firewall cleaning mode. If you specify "own", a conflict in the rules may occur.
|
||||
# This may cause a security issue. Use "own" if you are confident in your actions.
|
||||
# Valid values:
|
||||
# global = clears all rules completely
|
||||
# own = clears only the rules from the table that are specified in the table_name parameter
|
||||
#
|
||||
# Default: global
|
||||
###
|
||||
clear_mode = "global"
|
||||
|
||||
###
|
||||
# Будет ли демон сохранять правила в системный файл nftables.
|
||||
# Не забудьте проверить, что путь к nftables соответствует вашей ОС.
|
||||
@@ -409,6 +429,21 @@ default_allow_forward = false
|
||||
###
|
||||
input_drop = "drop"
|
||||
|
||||
###
|
||||
# Приоритет chain для input.
|
||||
# От: -50
|
||||
# По: 50
|
||||
#
|
||||
# По умолчанию: -10
|
||||
# ***
|
||||
# Chain priority for input.
|
||||
# From: -50
|
||||
# To: 50
|
||||
#
|
||||
# Default: -10
|
||||
###
|
||||
input_priority = -10
|
||||
|
||||
###
|
||||
# Как заблокировать исходящий трафик. Блокировать молча или с обратной связью.
|
||||
# Допустимые значения:
|
||||
@@ -426,6 +461,21 @@ input_drop = "drop"
|
||||
###
|
||||
output_drop = "reject"
|
||||
|
||||
###
|
||||
# Приоритет chain для output.
|
||||
# От: -50
|
||||
# По: 50
|
||||
#
|
||||
# По умолчанию: -10
|
||||
# ***
|
||||
# Chain priority for output.
|
||||
# From: -50
|
||||
# To: 50
|
||||
#
|
||||
# Default: -10
|
||||
###
|
||||
output_priority = -10
|
||||
|
||||
###
|
||||
# Как заблокировать трафик forward. Блокировать молча или с обратной связью.
|
||||
# Допустимые значения:
|
||||
@@ -443,6 +493,21 @@ output_drop = "reject"
|
||||
###
|
||||
forward_drop = "drop"
|
||||
|
||||
###
|
||||
# Приоритет chain для forward.
|
||||
# От: -50
|
||||
# По: 50
|
||||
#
|
||||
# По умолчанию: -10
|
||||
# ***
|
||||
# Chain priority for forward.
|
||||
# From: -50
|
||||
# To: 50
|
||||
#
|
||||
# Default: -10
|
||||
###
|
||||
forward_priority = -10
|
||||
|
||||
###############################################################################
|
||||
# РАЗДЕЛ:Именование метаданных
|
||||
# ***
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
nft "git.kor-elf.net/kor-elf-shield/go-nftables-client"
|
||||
nftFamily "git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
|
||||
)
|
||||
@@ -9,13 +11,13 @@ type Chains interface {
|
||||
NewPacketFilter(enable bool) error
|
||||
PacketFilter() PacketFilter
|
||||
|
||||
NewInput(chain string, defaultAllow bool) error
|
||||
NewInput(chain string, defaultAllow bool, priority int) error
|
||||
Input() Input
|
||||
|
||||
NewOutput(chain string, defaultAllow bool) error
|
||||
NewOutput(chain string, defaultAllow bool, priority int) error
|
||||
Output() Output
|
||||
|
||||
NewForward(chain string, defaultAllow bool) error
|
||||
NewForward(chain string, defaultAllow bool, priority int) error
|
||||
Forward() Forward
|
||||
|
||||
NewLocalInput() error
|
||||
@@ -23,6 +25,8 @@ type Chains interface {
|
||||
|
||||
NewLocalOutput() error
|
||||
LocalOutput() LocalOutput
|
||||
|
||||
ClearRules() error
|
||||
}
|
||||
|
||||
type chains struct {
|
||||
@@ -40,11 +44,12 @@ type chains struct {
|
||||
}
|
||||
|
||||
func NewChains(nft nft.NFT, table string) (Chains, error) {
|
||||
if err := nft.Clear(); err != nil {
|
||||
family := nftFamily.INET
|
||||
|
||||
if err := clearRules(nft, family, table); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
family := nftFamily.INET
|
||||
if err := nft.Table().Add(family, table); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -70,8 +75,8 @@ func (c *chains) PacketFilter() PacketFilter {
|
||||
return c.packetFilter
|
||||
}
|
||||
|
||||
func (c *chains) NewInput(chain string, defaultAllow bool) error {
|
||||
input, err := newInput(c.nft, c.family, c.table, chain, defaultAllow)
|
||||
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
|
||||
}
|
||||
@@ -84,8 +89,8 @@ func (c *chains) Input() Input {
|
||||
return c.input
|
||||
}
|
||||
|
||||
func (c *chains) NewOutput(chain string, defaultAllow bool) error {
|
||||
output, err := newOutput(c.nft, c.family, c.table, chain, defaultAllow)
|
||||
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
|
||||
}
|
||||
@@ -98,8 +103,8 @@ func (c *chains) Output() Output {
|
||||
return c.output
|
||||
}
|
||||
|
||||
func (c *chains) NewForward(chain string, defaultAllow bool) error {
|
||||
forward, err := newForward(c.nft, c.family, c.table, chain, defaultAllow)
|
||||
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
|
||||
}
|
||||
@@ -137,3 +142,17 @@ func (c *chains) NewLocalOutput() error {
|
||||
func (c *chains) LocalOutput() LocalOutput {
|
||||
return c.localOutput
|
||||
}
|
||||
|
||||
func (c *chains) ClearRules() error {
|
||||
return clearRules(c.nft, c.family, c.table)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ type forward struct {
|
||||
chain string
|
||||
}
|
||||
|
||||
func newForward(nft nft.NFT, family family.Type, table string, chain string, defaultAllow bool) (Forward, error) {
|
||||
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
|
||||
@@ -26,7 +26,7 @@ func newForward(nft nft.NFT, family family.Type, table string, chain string, def
|
||||
baseChain := nftChain.BaseChainOptions{
|
||||
Type: nftChain.TypeFilter,
|
||||
Hook: nftChain.HookForward,
|
||||
Priority: 0,
|
||||
Priority: int32(priority),
|
||||
Policy: policy,
|
||||
Device: "",
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ type input struct {
|
||||
chain string
|
||||
}
|
||||
|
||||
func newInput(nft nft.NFT, family family.Type, table string, chain string, defaultAllow bool) (Input, error) {
|
||||
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
|
||||
@@ -26,7 +26,7 @@ func newInput(nft nft.NFT, family family.Type, table string, chain string, defau
|
||||
baseChain := nftChain.BaseChainOptions{
|
||||
Type: nftChain.TypeFilter,
|
||||
Hook: nftChain.HookInput,
|
||||
Priority: 0,
|
||||
Priority: int32(priority),
|
||||
Policy: policy,
|
||||
Device: "",
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ type output struct {
|
||||
chain string
|
||||
}
|
||||
|
||||
func newOutput(nft nft.NFT, family family.Type, table string, chain string, defaultAllow bool) (Output, error) {
|
||||
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
|
||||
@@ -26,7 +26,7 @@ func newOutput(nft nft.NFT, family family.Type, table string, chain string, defa
|
||||
baseChain := nftChain.BaseChainOptions{
|
||||
Type: nftChain.TypeFilter,
|
||||
Hook: nftChain.HookOutput,
|
||||
Priority: 0,
|
||||
Priority: int32(priority),
|
||||
Policy: policy,
|
||||
Device: "",
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ type Config struct {
|
||||
}
|
||||
|
||||
type ConfigOptions struct {
|
||||
ClearMode ClearMode
|
||||
SavesRules bool
|
||||
SavesRulesPath string
|
||||
DnsStrict bool
|
||||
@@ -32,8 +33,11 @@ type ConfigPolicy struct {
|
||||
DefaultAllowOutput bool
|
||||
DefaultAllowForward bool
|
||||
InputDrop PolicyDrop
|
||||
InputPriority int
|
||||
OutputDrop PolicyDrop
|
||||
OutputPriority int
|
||||
ForwardDrop PolicyDrop
|
||||
ForwardPriority int
|
||||
}
|
||||
|
||||
type PolicyDrop int8
|
||||
@@ -143,3 +147,10 @@ func (d Direction) String() string {
|
||||
return fmt.Sprintf("Direction(%d)", d)
|
||||
}
|
||||
}
|
||||
|
||||
type ClearMode int8
|
||||
|
||||
const (
|
||||
ClearModeGlobal ClearMode = iota + 1
|
||||
ClearModeOwn
|
||||
)
|
||||
|
||||
@@ -43,6 +43,12 @@ func New(pathNFT string, logger log.Logger, config Config) (API, error) {
|
||||
|
||||
func (f *firewall) Reload() error {
|
||||
f.logger.Debug("Reload nftables rules")
|
||||
if f.config.Options.ClearMode == ClearModeGlobal {
|
||||
if err := f.nft.Clear(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
chains, err := chain.NewChains(f.nft, f.config.MetadataNaming.TableName)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -67,9 +73,20 @@ func (f *firewall) Reload() error {
|
||||
|
||||
func (f *firewall) ClearRules() {
|
||||
f.logger.Debug("Clear nftables rules")
|
||||
|
||||
switch f.config.Options.ClearMode {
|
||||
case ClearModeGlobal:
|
||||
if err := f.nft.Clear(); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to clear rules: %s", err))
|
||||
}
|
||||
break
|
||||
case ClearModeOwn:
|
||||
if err := f.chains.ClearRules(); err != nil {
|
||||
f.logger.Error(fmt.Sprintf("Failed to clear rules: %s", err))
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
f.logger.Debug("Clear nftables rules done")
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package firewall
|
||||
|
||||
func (f *firewall) reloadForward() error {
|
||||
f.logger.Debug("Reloading forward chain")
|
||||
err := f.chains.NewForward(f.config.MetadataNaming.ChainForwardName, f.config.Policy.DefaultAllowForward)
|
||||
err := f.chains.NewForward(f.config.MetadataNaming.ChainForwardName, f.config.Policy.DefaultAllowForward, f.config.Policy.ForwardPriority)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
func (f *firewall) reloadInput() error {
|
||||
f.logger.Debug("Reloading input chain")
|
||||
err := f.chains.NewInput(f.config.MetadataNaming.ChainInputName, f.config.Policy.DefaultAllowInput)
|
||||
err := f.chains.NewInput(f.config.MetadataNaming.ChainInputName, f.config.Policy.DefaultAllowInput, f.config.Policy.InputPriority)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
func (f *firewall) reloadOutput() error {
|
||||
f.logger.Debug("Reloading output chain")
|
||||
err := f.chains.NewOutput(f.config.MetadataNaming.ChainOutputName, f.config.Policy.DefaultAllowOutput)
|
||||
err := f.chains.NewOutput(f.config.MetadataNaming.ChainOutputName, f.config.Policy.DefaultAllowOutput, f.config.Policy.OutputPriority)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,10 +4,12 @@ import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/daemon/firewall"
|
||||
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/setting/validate"
|
||||
)
|
||||
|
||||
type options struct {
|
||||
ClearMode string `mapstructure:"clear_mode"`
|
||||
SavesRules bool `mapstructure:"saves_rules"`
|
||||
SavesRulesPath string `mapstructure:"saves_rules_path"`
|
||||
DnsStrict bool `mapstructure:"dns_strict"`
|
||||
@@ -17,6 +19,7 @@ type options struct {
|
||||
|
||||
func defaultOptions() options {
|
||||
return options{
|
||||
ClearMode: "global",
|
||||
SavesRules: false,
|
||||
SavesRulesPath: "/etc/nftables.conf",
|
||||
DnsStrict: false,
|
||||
@@ -45,3 +48,14 @@ func (o options) ValidateSavesRulesPath() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o options) ToClearMode() (firewall.ClearMode, error) {
|
||||
switch o.ClearMode {
|
||||
case "global":
|
||||
return firewall.ClearModeGlobal, nil
|
||||
case "own":
|
||||
return firewall.ClearModeOwn, nil
|
||||
}
|
||||
|
||||
return firewall.ClearModeGlobal, errors.New("invalid option clear_mode. Must be 'global' or 'own'")
|
||||
}
|
||||
|
||||
@@ -11,8 +11,11 @@ type policy struct {
|
||||
DefaultAllowOutput bool `mapstructure:"default_allow_output"`
|
||||
DefaultAllowForward bool `mapstructure:"default_allow_forward"`
|
||||
InputDrop string `mapstructure:"input_drop"`
|
||||
InputPriority int `mapstructure:"input_priority"`
|
||||
OutputDrop string `mapstructure:"output_drop"`
|
||||
OutputPriority int `mapstructure:"output_priority"`
|
||||
ForwardDrop string `mapstructure:"forward_drop"`
|
||||
ForwardPriority int `mapstructure:"forward_priority"`
|
||||
}
|
||||
|
||||
func defaultPolicy() policy {
|
||||
@@ -21,8 +24,11 @@ func defaultPolicy() policy {
|
||||
DefaultAllowOutput: false,
|
||||
DefaultAllowForward: false,
|
||||
InputDrop: "drop",
|
||||
InputPriority: -10,
|
||||
OutputDrop: "reject",
|
||||
OutputPriority: -10,
|
||||
ForwardDrop: "drop",
|
||||
ForwardPriority: -10,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +53,11 @@ func (p policy) ToConfigPolicy() (firewall.ConfigPolicy, error) {
|
||||
DefaultAllowOutput: p.DefaultAllowOutput,
|
||||
DefaultAllowForward: p.DefaultAllowForward,
|
||||
InputDrop: inputDrop,
|
||||
InputPriority: p.InputPriority,
|
||||
OutputDrop: outputDrop,
|
||||
OutputPriority: p.OutputPriority,
|
||||
ForwardDrop: forwardDrop,
|
||||
ForwardPriority: p.ForwardPriority,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -70,12 +79,23 @@ func (p policy) Validate() error {
|
||||
if err := validateDrop(p.InputDrop, "input_drop"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validatePriority(p.InputPriority, "input_priority"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := validateDrop(p.OutputDrop, "output_drop"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validatePriority(p.OutputPriority, "output_priority"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := validateDrop(p.ForwardDrop, "forward_drop"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validatePriority(p.ForwardPriority, "forward_priority"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -86,3 +106,10 @@ func validateDrop(drop string, parameterName string) error {
|
||||
}
|
||||
return fmt.Errorf("invalid %s. Must be drop or reject", parameterName)
|
||||
}
|
||||
|
||||
func validatePriority(priority int, parameterName string) error {
|
||||
if priority < -50 || priority > 50 {
|
||||
return fmt.Errorf("%s must be in range -50-50", parameterName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -36,6 +36,11 @@ func (o *otherSettingsPath) ToFirewallConfig() (firewall.Config, error) {
|
||||
return firewall.Config{}, err
|
||||
}
|
||||
|
||||
optionClearMode, err := setting.Options.ToClearMode()
|
||||
if err != nil {
|
||||
return firewall.Config{}, err
|
||||
}
|
||||
|
||||
return firewall.Config{
|
||||
InPorts: inPorts,
|
||||
OutPorts: outPorts,
|
||||
@@ -55,6 +60,7 @@ func (o *otherSettingsPath) ToFirewallConfig() (firewall.Config, error) {
|
||||
OutIPs: IPs.OutIP6,
|
||||
},
|
||||
Options: firewall.ConfigOptions{
|
||||
ClearMode: optionClearMode,
|
||||
SavesRules: setting.Options.SavesRules,
|
||||
SavesRulesPath: setting.Options.SavesRulesPath,
|
||||
DnsStrict: setting.Options.DnsStrict,
|
||||
|
||||
Reference in New Issue
Block a user