Compare commits

5 Commits

3 changed files with 167 additions and 1 deletions

88
README.md Normal file
View File

@@ -0,0 +1,88 @@
# go-nftables-client
Go-низкоуровневая обёртка для управления [nftables](https://wiki.nftables.org/wiki-nftables/index.php/Main_Page) через командную строку.
## Возможности
- Добавление и удаление таблиц (`add table`, `delete table`)
- Добавление и удаление цепочек (`add chain`, `delete chain`, настройка hook/policy)
- Добавление, удаление, очистка правил (`add rule`, `delete rule`, `flush`)
- Абстракции для работы с IP/IP6/inet/arp/bridge/netdev families
- Интерфейс для выполнения CLI-команд nftables напрямую
- Простой и минималистичный API для быстрой интеграции
## Установка
```sh
go get git.kor-elf.net/kor-elf-shield/go-nftables-client
```
## Пример использования
```go
package main
import (
"log"
"git.kor-elf.net/kor-elf-shield/go-nftables-client"
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
"git.kor-elf.net/kor-elf-shield/go-nftables-client/chain"
)
func main() {
nft, err := nft.New()
if err != nil {
log.Fatalf("nft not found: %v", err)
}
// Добавить таблицу
if err := nft.Table().Add(family.IP, "test"); err != nil {
log.Fatalf("table add failed: %v", err)
}
chainType := chain.NewBaseChainOptions(chain.TypeFilter)
chainType.Hook = chain.HookOutput
chainType.Priority = 0
chainType.Policy = chain.PolicyAccept
if err := nft.Chain().Add(family.IP, "test", "test", chainType); err != nil {
log.Fatalf("table add failed: %v", err)
}
// Добавить правило (пример: дропать пакеты от 1.2.3.4)
if err := nft.Rule().Add(family.IP, "test", "test", "ip", "saddr", "1.2.3.4", "drop"); err != nil {
log.Fatalf("rule add failed: %v", err)
}
}
```
## Краткое описание API
```go
nft.Table().Add(family.Type, tableName string) error
nft.Table().Delete(family.Type, tableName string) error
nft.Table().Clear(family.Type, tableName string) error
nft.Chain().Add(family.Type, table, chain string, baseChain chain.ChainOptions) error
nft.Chain().Create(family family.Type, table, chain string, baseChain chain.ChainOptions) error
nft.Chain().Rename(family family.Type, table, oldChainName, newChainName string) error
nft.Chain().Delete(family.Type, table, chain string) error
nft.Chain().Clear(family.Type, table, chain string) error
nft.Rule().Add(family.Type, table, chain string, expr ...string) error
nft.Rule().Insert(family family.Type, table, chain string, expr ...string) error
nft.Rule().Replace(family family.Type, table, chain string, handle uint64, expr ...string) error
nft.Rule().Delete(family family.Type, table, chain string, handle uint64) error
nft.Clear() error // flush ruleset
nft.Version() (Version, error) // информация о версии nftables
nft.Command() command.NFT // ручное выполнение любых nft-команд
```
## Требования
- Go 1.25+
- Установленный nft (`/usr/sbin/nft`, `/sbin/nft` или доступен через PATH)
## Лицензия
[MIT](https://git.kor-elf.net/kor-elf-shield/go-nftables-client/src/branch/main/LICENSE)

68
internal/rule/rule.go Normal file
View File

@@ -0,0 +1,68 @@
package rule
import (
"strconv"
"git.kor-elf.net/kor-elf-shield/go-nftables-client/family"
"git.kor-elf.net/kor-elf-shield/go-nftables-client/internal/command"
)
type API interface {
// Add adds a new rule.
//
// This command is equivalent to:
// nft add rule (ip|ip6|inet|arp|bridge) {table_name} {chain_name} '{ expr }'
Add(family family.Type, tableName string, chainName string, expr ...string) error
// Insert inserts a new rule.
// Inserted rules are placed at the beginning of the chain, by default.
//
// This command is equivalent to:
// nft insert rule (ip|ip6|inet|arp|bridge) {table_name} {chain_name} '{ expr }'
Insert(family family.Type, tableName string, chainName string, expr ...string) error
// Replace replaces a rule.
//
// This command is equivalent to:
// nft replace rule (ip|ip6|inet|arp|bridge) {table_name} {chain_name} {handle} '{ expr }'
Replace(family family.Type, tableName string, chainName string, handle uint64, expr ...string) error
// Delete deletes a rule.
//
// This command is equivalent to:
// nft delete rule (ip|ip6|inet|arp|bridge) {table_name} {chain_name} {handle}
Delete(family family.Type, tableName string, chainName string, handle uint64) error
}
type rule struct {
command command.NFT
}
func New(command command.NFT) API {
return &rule{
command: command,
}
}
func (r *rule) Add(family family.Type, tableName string, chainName string, expr ...string) error {
args := []string{"add", "rule", family.String(), tableName, chainName}
args = append(args, expr...)
return r.command.Run(args...)
}
func (r *rule) Insert(family family.Type, tableName string, chainName string, expr ...string) error {
args := []string{"insert", "rule", family.String(), tableName, chainName}
args = append(args, expr...)
return r.command.Run(args...)
}
func (r *rule) Replace(family family.Type, tableName string, chainName string, handle uint64, expr ...string) error {
args := []string{"replace", "rule", family.String(), tableName, chainName, "handle", strconv.Itoa(int(handle))}
args = append(args, expr...)
return r.command.Run(args...)
}
func (r *rule) Delete(family family.Type, tableName string, chainName string, handle uint64) error {
args := []string{"delete", "rule", family.String(), tableName, chainName, "handle", strconv.Itoa(int(handle))}
return r.command.Run(args...)
}

12
nft.go
View File

@@ -7,6 +7,7 @@ import (
"git.kor-elf.net/kor-elf-shield/go-nftables-client/internal/chain" "git.kor-elf.net/kor-elf-shield/go-nftables-client/internal/chain"
"git.kor-elf.net/kor-elf-shield/go-nftables-client/internal/command" "git.kor-elf.net/kor-elf-shield/go-nftables-client/internal/command"
"git.kor-elf.net/kor-elf-shield/go-nftables-client/internal/rule"
"git.kor-elf.net/kor-elf-shield/go-nftables-client/internal/table" "git.kor-elf.net/kor-elf-shield/go-nftables-client/internal/table"
) )
@@ -33,12 +34,16 @@ type NFT interface {
// Chain returns an API for working with chains. // Chain returns an API for working with chains.
Chain() chain.API Chain() chain.API
// Rule returns an API for working with rules.
Rule() rule.API
} }
type nft struct { type nft struct {
command command.NFT command command.NFT
table table.API table table.API
chain chain.API chain chain.API
rule rule.API
} }
// New Returns a client for working with nftables. // New Returns a client for working with nftables.
@@ -66,6 +71,7 @@ func NewWithPath(path string) (NFT, error) {
command: nftCommand, command: nftCommand,
table: table.New(nftCommand), table: table.New(nftCommand),
chain: chain.New(nftCommand), chain: chain.New(nftCommand),
rule: rule.New(nftCommand),
}, nil }, nil
} }
@@ -84,7 +90,7 @@ func (n *nft) Version() (Version, error) {
vers := "" vers := ""
opts := make(map[string]string) opts := make(map[string]string)
lines := regexp.MustCompile("\r?\n").Split(strings.TrimSpace(string(out)), -1) lines := regexp.MustCompile("\r?\n").Split(strings.TrimSpace(out), -1)
for index, line := range lines { for index, line := range lines {
line = strings.TrimSpace(line) line = strings.TrimSpace(line)
@@ -116,6 +122,10 @@ func (n *nft) Chain() chain.API {
return n.chain return n.chain
} }
func (n *nft) Rule() rule.API {
return n.rule
}
func (n *nft) Command() command.NFT { func (n *nft) Command() command.NFT {
return n.command return n.command
} }