Add command for removing IP addresses from the block list

- Introduced `block delete` command to remove IPs from the block list.
- Added `UnblockIP` method to support IP removal in the firewall.
- Updated internationalization files for delete command descriptions.
- Enhanced repository with `DeleteByIP` for targeted IP removal.
This commit is contained in:
2026-03-09 21:21:28 +05:00
parent a7e4c7d750
commit 221fdb8d3b
8 changed files with 163 additions and 6 deletions

View File

@@ -36,6 +36,12 @@ func CmdBlock() *cli.Command {
},
},
},
{
Name: "delete",
Usage: i18n.Lang.T("cmd.daemon.block.delete.Usage"),
Description: i18n.Lang.T("cmd.daemon.block.delete.Description"),
Action: cmdBlockDelete,
},
{
Name: "clear",
Usage: i18n.Lang.T("cmd.daemon.block.clear.Usage"),
@@ -80,6 +86,37 @@ func cmdBlockAdd(_ context.Context, cmd *cli.Command) error {
return nil
}
func cmdBlockDelete(_ context.Context, cmd *cli.Command) error {
ip := net.ParseIP(cmd.Args().Get(0))
if ip == nil {
return errors.New("invalid ip address")
}
sock, err := newSocket()
if err != nil {
return errors.New(i18n.Lang.T("daemon is not running"))
}
defer func() {
_ = sock.Close()
}()
result, err := sock.SendCommand("block_delete_ip", map[string]string{
"ip": ip.String(),
})
if err != nil {
return err
}
if result != "ok" {
return errors.New(i18n.Lang.T("cmd.error", map[string]any{
"Error": result,
}))
}
fmt.Println(i18n.Lang.T("block_delete_ip_success"))
return nil
}
func cmdBlockClear(_ context.Context, _ *cli.Command) error {
sock, err := newSocket()
if err != nil {

View File

@@ -160,24 +160,43 @@ func (d *daemon) socketCommand(command string, args map[string]string, socket so
if args["ip"] == "" {
return socket.Write("ip argument is required")
}
ip := net.ParseIP(args["ip"])
if ip == nil {
ipAddr := net.ParseIP(args["ip"])
if ipAddr == nil {
_ = socket.Write("invalid ip address")
return errors.New("invalid ip address")
}
port := args["port"]
if port != "" {
if err := d.cmdBlockAddIPWithPort(ip, port, args); err != nil {
return socket.Write("block add failed: " + err.Error())
if err := d.cmdBlockAddIPWithPort(ipAddr, port, args); err != nil {
_ = socket.Write("block add failed: " + err.Error())
return err
}
} else {
if err := d.cmdBlockAddIP(ip, args); err != nil {
return socket.Write("block add failed: " + err.Error())
if err := d.cmdBlockAddIP(ipAddr, args); err != nil {
_ = socket.Write("block add failed: " + err.Error())
return err
}
}
return socket.Write("ok")
case "block_delete_ip":
if args["ip"] == "" {
return socket.Write("ip argument is required")
}
ipAddr := net.ParseIP(args["ip"])
if ipAddr == nil {
_ = socket.Write("invalid ip address")
return errors.New("invalid ip address")
}
if err := d.firewall.UnblockIP(ipAddr); err != nil {
_ = socket.Write("block delete failed: " + err.Error())
return err
}
return socket.Write("ok")
case "block_clear":
if err := d.firewall.UnblockAllIPs(); err != nil {
_ = socket.Write("block clear failed: " + err.Error())

View File

@@ -3,6 +3,7 @@ package repository
import (
"encoding/json"
"errors"
"net"
"time"
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/daemon/db/entity"
@@ -13,6 +14,7 @@ import (
type BlockingRepository interface {
Add(blockedIP entity.Blocking) error
List(callback func(entity.Blocking) error) error
DeleteByIP(ip net.IP, callback func(entity.Blocking) error) error
DeleteExpired(limit int) (int, error)
Clear() error
}
@@ -73,6 +75,44 @@ func (r *blocking) List(callback func(entity.Blocking) error) error {
})
}
func (r *blocking) DeleteByIP(ip net.IP, callback func(entity.Blocking) error) error {
return r.db.Update(func(tx *bbolt.Tx) error {
bucket, err := tx.CreateBucketIfNotExists([]byte(r.bucket))
if err != nil {
return err
}
c := bucket.Cursor()
for k, v := c.First(); k != nil; {
blockedIP := entity.Blocking{}
err := json.Unmarshal(v, &blockedIP)
if err != nil {
return err
}
parsedBlockedIP := net.ParseIP(blockedIP.IP)
if parsedBlockedIP == nil || !parsedBlockedIP.Equal(ip) {
k, v = c.Next()
continue
}
if err := callback(blockedIP); err != nil {
return err
}
nextK, nextV := c.Next()
if err := bucket.Delete(k); err != nil {
return err
}
k = nextK
v = nextV
}
return nil
})
}
func (r *blocking) DeleteExpired(limit int) (int, error) {
if limit <= 0 {
return 0, nil

View File

@@ -19,6 +19,7 @@ type API interface {
BlockIP(block BlockIP) (bool, error)
BlockIPWithPorts(block BlockIPWithPorts) (bool, error)
UnblockAllIPs() error
UnblockIP(ip net.IP) error
ClearDBData() error
}
@@ -171,6 +172,33 @@ func (b *blocking) BlockIPWithPorts(block BlockIPWithPorts) (bool, error) {
return true, nil
}
func (b *blocking) UnblockIP(ip net.IP) error {
err := b.blockingRepository.DeleteByIP(ip, func(e entity.Blocking) error {
if e.IsPorts() {
l4Ports, err := e.ToL4Ports()
if err != nil {
return err
}
return b.removeIPWithPorts(ip, l4Ports)
}
if err := b.blockListIP.DeleteIP(ip); err != nil {
if strings.Contains(err.Error(), "element does not exist") {
return nil
}
return err
}
return nil
})
if err != nil {
return err
}
return nil
}
func (b *blocking) UnblockAllIPs() error {
err := b.blockingRepository.List(func(e entity.Blocking) error {
ip := net.ParseIP(e.IP)
@@ -214,3 +242,16 @@ func (b *blocking) UnblockAllIPs() error {
func (b *blocking) ClearDBData() error {
return b.blockingRepository.Clear()
}
func (b *blocking) removeIPWithPorts(ip net.IP, l4Ports []types.L4Port) error {
for _, port := range l4Ports {
if err := b.blockListIPWithPort.DeleteIP(ip, port); err != nil {
if strings.Contains(err.Error(), "element does not exist") ||
strings.Contains(err.Error(), "Error: Could not process rule: No such file or directory") {
continue
}
return err
}
}
return nil
}

View File

@@ -2,6 +2,7 @@ package firewall
import (
"fmt"
"net"
"os"
"git.kor-elf.net/kor-elf-shield/kor-elf-shield/internal/daemon/docker_monitor"
@@ -31,6 +32,9 @@ type API interface {
// UnblockAllIPs Unblock all IP addresses.
UnblockAllIPs() error
// UnblockIP Unblock IP address.
UnblockIP(ip net.IP) error
// ClearDBData Clear all data from DB
ClearDBData() error
@@ -129,6 +133,10 @@ func (f *firewall) UnblockAllIPs() error {
return f.blockingService.UnblockAllIPs()
}
func (f *firewall) UnblockIP(ip net.IP) error {
return f.blockingService.UnblockIP(ip)
}
func (f *firewall) ClearDBData() error {
return f.blockingService.ClearDBData()
}

View File

@@ -38,6 +38,10 @@
"cmd.daemon.block.add.FlagUsage.reason": "Reason for blocking.",
"block_add_ip_success": "The IP address has been successfully added to the block list.",
"cmd.daemon.block.delete.Usage": "Remove IP address from block list",
"cmd.daemon.block.delete.Description": "Remove an IP address from the block list. \nExample: \nkor-elf-shield block delete 192.168.1.1",
"block_delete_ip_success": "The IP address has been successfully removed from the block list.",
"Command error": "Command error",
"invalid log level": "The log level specified in the settings is invalid. It is currently set to: {{.Level}}. Valid values: {{.Levels}}",
"invalid log encoding": "Invalid encoding setting. Currently set to: {{.Encoding}}. Valid values: {{.Encodings}}",

View File

@@ -38,6 +38,10 @@
"cmd.daemon.block.add.FlagUsage.reason": "Блоктау себебі.",
"block_add_ip_success": "IP мекенжайы блоктау тізіміне сәтті қосылды.",
"cmd.daemon.block.delete.Usage": "IP мекенжайын блоктау тізімінен алып тастаңыз",
"cmd.daemon.block.delete.Description": "IP мекенжайын блоктау тізімінен алып тастаңыз. \nМысал: \nkor-elf-shield block delete 192.168.1.1",
"block_delete_ip_success": "IP мекенжайы блоктау тізімінен сәтті жойылды.",
"Command error": "Командалық қате",
"invalid log level": "Параметрлерде көрсетілген журнал деңгейі жарамсыз. Ол қазір мына күйге орнатылған: {{.Level}}. Жарамды мәндер: {{.Levels}}",
"invalid log encoding": "Жарамсыз кодтау параметрі. Қазіргі уақытта орнатылған: {{.Encoding}}. Жарамды мәндер: {{.Encodings}}",

View File

@@ -38,6 +38,10 @@
"cmd.daemon.block.add.FlagUsage.reason": "Причина блокировки.",
"block_add_ip_success": "IP адрес успешно добавлен в список заблокированных.",
"cmd.daemon.block.delete.Usage": "Удалить IP адрес из списка заблокированных",
"cmd.daemon.block.delete.Description": "Удалить IP адрес из списка заблокированных. \nПример: \nkor-elf-shield block delete 192.168.1.1",
"block_delete_ip_success": "IP адрес успешно удален из списка заблокированных.",
"Command error": "Ошибка команды",
"invalid log level": "В настройках указан не верный уровень log. Сейчас указан: {{.Level}}. Допустимые значения: {{.Levels}}",
"invalid log encoding": "Неверная настройка encoding. Сейчас указан: {{.Encoding}}. Допустимые значения: {{.Encodings}}",