2024-08-27 03:07:58 +03:00
|
|
|
package main
|
|
|
|
|
2024-08-30 04:30:33 +03:00
|
|
|
import (
|
|
|
|
"fmt"
|
2024-08-30 05:27:52 +03:00
|
|
|
"net"
|
2024-09-04 08:14:09 +03:00
|
|
|
"os"
|
2024-08-30 05:27:52 +03:00
|
|
|
"time"
|
2024-08-30 04:30:33 +03:00
|
|
|
|
|
|
|
"kvas2-go/models"
|
|
|
|
"kvas2-go/pkg/ip-helper"
|
2024-09-04 10:30:18 +03:00
|
|
|
|
|
|
|
"github.com/vishvananda/netlink"
|
2024-08-30 04:30:33 +03:00
|
|
|
)
|
2024-08-27 03:07:58 +03:00
|
|
|
|
2024-08-30 04:09:28 +03:00
|
|
|
type GroupOptions struct {
|
|
|
|
Enabled bool
|
2024-09-04 10:30:18 +03:00
|
|
|
ipRule *netlink.Rule
|
2024-08-30 04:09:28 +03:00
|
|
|
}
|
|
|
|
|
2024-08-27 03:07:58 +03:00
|
|
|
type Group struct {
|
|
|
|
*models.Group
|
2024-08-30 04:40:46 +03:00
|
|
|
ipsetName string
|
|
|
|
options GroupOptions
|
2024-08-27 03:07:58 +03:00
|
|
|
}
|
2024-08-30 04:30:33 +03:00
|
|
|
|
2024-08-30 05:27:52 +03:00
|
|
|
func (g *Group) HandleIPv4(names []string, address net.IP, ttl time.Duration) error {
|
|
|
|
if !g.options.Enabled {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-09-04 08:14:09 +03:00
|
|
|
ttlSeconds := uint32(ttl.Seconds())
|
|
|
|
|
2024-08-30 05:27:52 +03:00
|
|
|
DomainSearch:
|
|
|
|
for _, domain := range g.Domains {
|
|
|
|
if !domain.IsEnabled() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
for _, name := range names {
|
|
|
|
if domain.IsMatch(name) {
|
2024-09-04 08:14:09 +03:00
|
|
|
err := netlink.IpsetAdd(g.ipsetName, &netlink.IPSetEntry{
|
|
|
|
IP: address,
|
|
|
|
Timeout: &ttlSeconds,
|
|
|
|
Replace: true,
|
|
|
|
})
|
2024-08-30 05:27:52 +03:00
|
|
|
if err != nil {
|
2024-09-04 09:15:03 +03:00
|
|
|
return fmt.Errorf("failed to assign address: %w", err)
|
2024-08-30 05:27:52 +03:00
|
|
|
}
|
|
|
|
break DomainSearch
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-08-30 04:30:33 +03:00
|
|
|
func (g *Group) Enable() error {
|
|
|
|
if g.options.Enabled {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-09-04 10:30:18 +03:00
|
|
|
var err error
|
|
|
|
|
|
|
|
rule := netlink.NewRule()
|
|
|
|
rule.Mark, err = ipHelper.GetUnusedFwMark(1)
|
2024-08-30 04:30:33 +03:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error while getting free fwmark: %w", err)
|
|
|
|
}
|
2024-09-04 10:30:18 +03:00
|
|
|
rule.Table, err = ipHelper.GetUnusedTable(1)
|
2024-08-30 04:30:33 +03:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error while getting free table: %w", err)
|
|
|
|
}
|
2024-09-04 10:30:18 +03:00
|
|
|
err = netlink.RuleAdd(rule)
|
2024-08-30 04:30:33 +03:00
|
|
|
if err != nil {
|
2024-09-04 10:30:18 +03:00
|
|
|
return fmt.Errorf("error while adding rule: %w", err)
|
2024-08-30 04:30:33 +03:00
|
|
|
}
|
2024-09-04 10:30:18 +03:00
|
|
|
g.options.ipRule = rule
|
2024-08-30 04:30:33 +03:00
|
|
|
|
2024-09-04 08:14:09 +03:00
|
|
|
defaultTimeout := uint32(300)
|
|
|
|
err = netlink.IpsetDestroy(g.ipsetName)
|
|
|
|
if err != nil && !os.IsNotExist(err) {
|
2024-08-30 04:40:46 +03:00
|
|
|
return fmt.Errorf("failed to destroy ipset: %w", err)
|
|
|
|
}
|
2024-09-04 08:14:09 +03:00
|
|
|
err = netlink.IpsetCreate(g.ipsetName, "hash:ip", netlink.IpsetCreateOptions{
|
|
|
|
Timeout: &defaultTimeout,
|
|
|
|
})
|
2024-08-30 04:40:46 +03:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to create ipset: %w", err)
|
|
|
|
}
|
|
|
|
|
2024-08-30 04:30:33 +03:00
|
|
|
g.options.Enabled = true
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *Group) Disable() error {
|
|
|
|
if !g.options.Enabled {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-09-04 10:30:18 +03:00
|
|
|
err := netlink.RuleDel(g.options.ipRule)
|
2024-08-30 04:30:33 +03:00
|
|
|
if err != nil {
|
2024-09-04 10:30:18 +03:00
|
|
|
return fmt.Errorf("error while deleting rule: %w", err)
|
2024-08-30 04:30:33 +03:00
|
|
|
}
|
|
|
|
|
2024-09-04 08:14:09 +03:00
|
|
|
err = netlink.IpsetDestroy(g.ipsetName)
|
|
|
|
if err != nil && !os.IsNotExist(err) {
|
2024-08-30 04:40:46 +03:00
|
|
|
return fmt.Errorf("failed to destroy ipset: %w", err)
|
|
|
|
}
|
|
|
|
|
2024-08-30 04:30:33 +03:00
|
|
|
g.options.Enabled = false
|
2024-09-04 10:30:18 +03:00
|
|
|
g.options.ipRule = nil
|
2024-08-30 04:30:33 +03:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|