Pull request: aghnet: fix ipset init errors
Updates #4027. Squashed commit of the following: commit 9ac0cc27ca94e630cc321c90b60b271499af4d9b Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Dec 27 20:26:22 2021 +0300 aghnet: fix ipset init errors
This commit is contained in:
parent
dea8a585f8
commit
2ed1f939b5
|
@ -29,6 +29,7 @@ and this project adheres to
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- `ipset` initialization bugs ([#4027]).
|
||||||
- Legacy DNS rewrites from a wildcard pattern to a subdomain ([#4016]).
|
- Legacy DNS rewrites from a wildcard pattern to a subdomain ([#4016]).
|
||||||
- Service not being stopped before running the `uninstall` service action
|
- Service not being stopped before running the `uninstall` service action
|
||||||
([#3868]).
|
([#3868]).
|
||||||
|
@ -46,6 +47,7 @@ and this project adheres to
|
||||||
[#3987]: https://github.com/AdguardTeam/AdGuardHome/issues/3987
|
[#3987]: https://github.com/AdguardTeam/AdGuardHome/issues/3987
|
||||||
[#4008]: https://github.com/AdguardTeam/AdGuardHome/issues/4008
|
[#4008]: https://github.com/AdguardTeam/AdGuardHome/issues/4008
|
||||||
[#4016]: https://github.com/AdguardTeam/AdGuardHome/issues/4016
|
[#4016]: https://github.com/AdguardTeam/AdGuardHome/issues/4016
|
||||||
|
[#4027]: https://github.com/AdguardTeam/AdGuardHome/issues/4027
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,12 @@ type IpsetManager interface {
|
||||||
//
|
//
|
||||||
// DOMAIN[,DOMAIN].../IPSET_NAME[,IPSET_NAME]...
|
// DOMAIN[,DOMAIN].../IPSET_NAME[,IPSET_NAME]...
|
||||||
//
|
//
|
||||||
// The error is of type *aghos.UnsupportedError if the OS is not supported.
|
// If ipsetConf is empty, msg and err are nil. The error is of type
|
||||||
|
// *aghos.UnsupportedError if the OS is not supported.
|
||||||
func NewIpsetManager(ipsetConf []string) (mgr IpsetManager, err error) {
|
func NewIpsetManager(ipsetConf []string) (mgr IpsetManager, err error) {
|
||||||
|
if len(ipsetConf) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
return newIpsetMgr(ipsetConf)
|
return newIpsetMgr(ipsetConf)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/digineo/go-ipset/v2"
|
"github.com/digineo/go-ipset/v2"
|
||||||
"github.com/mdlayher/netlink"
|
"github.com/mdlayher/netlink"
|
||||||
"github.com/ti-mo/netfilter"
|
"github.com/ti-mo/netfilter"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// How to test on a real Linux machine:
|
// How to test on a real Linux machine:
|
||||||
|
@ -42,11 +43,17 @@ import (
|
||||||
|
|
||||||
// newIpsetMgr returns a new Linux ipset manager.
|
// newIpsetMgr returns a new Linux ipset manager.
|
||||||
func newIpsetMgr(ipsetConf []string) (set IpsetManager, err error) {
|
func newIpsetMgr(ipsetConf []string) (set IpsetManager, err error) {
|
||||||
dial := func(pf netfilter.ProtoFamily, conf *netlink.Config) (conn ipsetConn, err error) {
|
return newIpsetMgrWithDialer(ipsetConf, defaultDial)
|
||||||
return ipset.Dial(pf, conf)
|
}
|
||||||
|
|
||||||
|
// defaultDial is the default netfilter dialing function.
|
||||||
|
func defaultDial(pf netfilter.ProtoFamily, conf *netlink.Config) (conn ipsetConn, err error) {
|
||||||
|
conn, err = ipset.Dial(pf, conf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return newIpsetMgrWithDialer(ipsetConf, dial)
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ipsetConn is the ipset conn interface.
|
// ipsetConn is the ipset conn interface.
|
||||||
|
@ -103,8 +110,8 @@ func (m *ipsetMgr) dialNetfilter(conf *netlink.Config) (err error) {
|
||||||
// The kernel API does not actually require two sockets but package
|
// The kernel API does not actually require two sockets but package
|
||||||
// github.com/digineo/go-ipset does.
|
// github.com/digineo/go-ipset does.
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): Perhaps we can ditch package ipset altogether and
|
// TODO(a.garipov): Perhaps we can ditch package ipset altogether and just
|
||||||
// just use packages netfilter and netlink.
|
// use packages netfilter and netlink.
|
||||||
m.ipv4Conn, err = m.dial(netfilter.ProtoIPv4, conf)
|
m.ipv4Conn, err = m.dial(netfilter.ProtoIPv4, conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("dialing v4: %w", err)
|
return fmt.Errorf("dialing v4: %w", err)
|
||||||
|
@ -214,6 +221,14 @@ func newIpsetMgrWithDialer(ipsetConf []string, dial ipsetDialer) (mgr IpsetManag
|
||||||
|
|
||||||
err = m.dialNetfilter(&netlink.Config{})
|
err = m.dialNetfilter(&netlink.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if errors.Is(err, unix.EPROTONOSUPPORT) {
|
||||||
|
// The implementation doesn't support this protocol version. Just
|
||||||
|
// issue a warning.
|
||||||
|
log.Info("ipset: dialing netfilter: warning: %s", err)
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("dialing netfilter: %w", err)
|
return nil, fmt.Errorf("dialing netfilter: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,20 +24,19 @@ type ipsetCtx struct {
|
||||||
func (c *ipsetCtx) init(ipsetConf []string) (err error) {
|
func (c *ipsetCtx) init(ipsetConf []string) (err error) {
|
||||||
c.ipsetMgr, err = aghnet.NewIpsetManager(ipsetConf)
|
c.ipsetMgr, err = aghnet.NewIpsetManager(ipsetConf)
|
||||||
if errors.Is(err, os.ErrInvalid) || errors.Is(err, os.ErrPermission) {
|
if errors.Is(err, os.ErrInvalid) || errors.Is(err, os.ErrPermission) {
|
||||||
// ipset cannot currently be initialized if the server was
|
// ipset cannot currently be initialized if the server was installed
|
||||||
// installed from Snap or when the user or the binary doesn't
|
// from Snap or when the user or the binary doesn't have the required
|
||||||
// have the required permissions, or when the kernel doesn't
|
// permissions, or when the kernel doesn't support netfilter.
|
||||||
// support netfilter.
|
|
||||||
//
|
//
|
||||||
// Log and go on.
|
// Log and go on.
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): The Snap problem can probably be solved if
|
// TODO(a.garipov): The Snap problem can probably be solved if we add
|
||||||
// we add the netlink-connector interface plug.
|
// the netlink-connector interface plug.
|
||||||
log.Info("warning: cannot initialize ipset: %s", err)
|
log.Info("ipset: warning: cannot initialize: %s", err)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
} else if unsupErr := (&aghos.UnsupportedError{}); errors.As(err, &unsupErr) {
|
} else if unsupErr := (&aghos.UnsupportedError{}); errors.As(err, &unsupErr) {
|
||||||
log.Info("warning: %s", err)
|
log.Info("ipset: warning: %s", err)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue