all: imp code
This commit is contained in:
parent
03c69ab272
commit
37ccae4e92
|
@ -616,7 +616,7 @@ func (s *Server) prepareInternalDNS() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ipsetLogger := s.logger.With(slogutil.KeyPrefix, "ipset")
|
ipsetLogger := s.logger.With(slogutil.KeyPrefix, "ipset")
|
||||||
s.ipset, err = newIpsetHandler(ipsetLogger, ipsetList)
|
s.ipset, err = newIpsetHandler(context.TODO(), ipsetLogger, ipsetList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't wrap the error, because it's informative enough as is.
|
// Don't wrap the error, because it's informative enough as is.
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -22,14 +22,19 @@ type ipsetHandler struct {
|
||||||
|
|
||||||
// newIpsetHandler returns a new initialized [ipsetHandler]. It is not safe for
|
// newIpsetHandler returns a new initialized [ipsetHandler]. It is not safe for
|
||||||
// concurrent use. c is always non-nil for [Server.Close].
|
// concurrent use. c is always non-nil for [Server.Close].
|
||||||
func newIpsetHandler(logger *slog.Logger, ipsetList []string) (c *ipsetHandler, err error) {
|
func newIpsetHandler(
|
||||||
c = &ipsetHandler{
|
ctx context.Context,
|
||||||
|
logger *slog.Logger,
|
||||||
|
ipsetList []string,
|
||||||
|
) (h *ipsetHandler, err error) {
|
||||||
|
h = &ipsetHandler{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
}
|
}
|
||||||
c.ipsetMgr, err = ipset.NewManager(&ipset.Config{
|
conf := &ipset.Config{
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
IpsetList: ipsetList,
|
Lines: ipsetList,
|
||||||
})
|
}
|
||||||
|
h.ipsetMgr, err = ipset.NewManager(ctx, conf)
|
||||||
if errors.Is(err, os.ErrInvalid) ||
|
if errors.Is(err, os.ErrInvalid) ||
|
||||||
errors.Is(err, os.ErrPermission) ||
|
errors.Is(err, os.ErrPermission) ||
|
||||||
errors.Is(err, errors.ErrUnsupported) {
|
errors.Is(err, errors.ErrUnsupported) {
|
||||||
|
@ -41,26 +46,27 @@ func newIpsetHandler(logger *slog.Logger, ipsetList []string) (c *ipsetHandler,
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): The Snap problem can probably be solved if we add
|
// TODO(a.garipov): The Snap problem can probably be solved if we add
|
||||||
// the netlink-connector interface plug.
|
// the netlink-connector interface plug.
|
||||||
logger.Warn("cannot initialize", slogutil.KeyError, err)
|
logger.WarnContext(ctx, "cannot initialize", slogutil.KeyError, err)
|
||||||
|
|
||||||
return c, nil
|
return h, nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return c, fmt.Errorf("initializing ipset: %w", err)
|
return h, fmt.Errorf("initializing ipset: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c, nil
|
return h, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// close closes the Linux Netfilter connections.
|
// close closes the Linux Netfilter connections.
|
||||||
func (c *ipsetHandler) close() (err error) {
|
func (h *ipsetHandler) close() (err error) {
|
||||||
if c.ipsetMgr != nil {
|
if h.ipsetMgr != nil {
|
||||||
return c.ipsetMgr.Close()
|
return h.ipsetMgr.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ipsetHandler) dctxIsfilled(dctx *dnsContext) (ok bool) {
|
// dctxIsFilled returns true if dctx has enough information to process.
|
||||||
|
func dctxIsFilled(dctx *dnsContext) (ok bool) {
|
||||||
return dctx != nil &&
|
return dctx != nil &&
|
||||||
dctx.responseFromUpstream &&
|
dctx.responseFromUpstream &&
|
||||||
dctx.proxyCtx != nil &&
|
dctx.proxyCtx != nil &&
|
||||||
|
@ -71,8 +77,8 @@ func (c *ipsetHandler) dctxIsfilled(dctx *dnsContext) (ok bool) {
|
||||||
|
|
||||||
// skipIpsetProcessing returns true when the ipset processing can be skipped for
|
// skipIpsetProcessing returns true when the ipset processing can be skipped for
|
||||||
// this request.
|
// this request.
|
||||||
func (c *ipsetHandler) skipIpsetProcessing(dctx *dnsContext) (ok bool) {
|
func (h *ipsetHandler) skipIpsetProcessing(dctx *dnsContext) (ok bool) {
|
||||||
if c == nil || c.ipsetMgr == nil || !c.dctxIsfilled(dctx) {
|
if h == nil || h.ipsetMgr == nil || !dctxIsFilled(dctx) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,13 +120,13 @@ func ipsFromAnswer(ans []dns.RR) (ip4s, ip6s []net.IP) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// process adds the resolved IP addresses to the domain's ipsets, if any.
|
// process adds the resolved IP addresses to the domain's ipsets, if any.
|
||||||
func (c *ipsetHandler) process(dctx *dnsContext) (rc resultCode) {
|
func (h *ipsetHandler) process(dctx *dnsContext) (rc resultCode) {
|
||||||
c.logger.Debug("started processing")
|
// TODO(s.chzhen): Use passed context.
|
||||||
defer c.logger.Debug("finished processing")
|
|
||||||
|
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
h.logger.DebugContext(ctx, "started processing")
|
||||||
|
defer h.logger.DebugContext(ctx, "finished processing")
|
||||||
|
|
||||||
if c.skipIpsetProcessing(dctx) {
|
if h.skipIpsetProcessing(dctx) {
|
||||||
return resultCodeSuccess
|
return resultCodeSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,15 +136,15 @@ func (c *ipsetHandler) process(dctx *dnsContext) (rc resultCode) {
|
||||||
host = strings.ToLower(host)
|
host = strings.ToLower(host)
|
||||||
|
|
||||||
ip4s, ip6s := ipsFromAnswer(dctx.proxyCtx.Res.Answer)
|
ip4s, ip6s := ipsFromAnswer(dctx.proxyCtx.Res.Answer)
|
||||||
n, err := c.ipsetMgr.Add(ctx, host, ip4s, ip6s)
|
n, err := h.ipsetMgr.Add(ctx, host, ip4s, ip6s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Consider ipset errors non-critical to the request.
|
// Consider ipset errors non-critical to the request.
|
||||||
c.logger.ErrorContext(ctx, "adding host ips", slogutil.KeyError, err)
|
h.logger.ErrorContext(ctx, "adding host ips", slogutil.KeyError, err)
|
||||||
|
|
||||||
return resultCodeSuccess
|
return resultCodeSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
c.logger.DebugContext(ctx, "added new ipset entries", "num", n)
|
h.logger.DebugContext(ctx, "added new ipset entries", "num", n)
|
||||||
|
|
||||||
return resultCodeSuccess
|
return resultCodeSuccess
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,23 +22,23 @@ type Config struct {
|
||||||
// not be nil.
|
// not be nil.
|
||||||
Logger *slog.Logger
|
Logger *slog.Logger
|
||||||
|
|
||||||
// IpsetList is the ipset configuration with the following syntax:
|
// Lines is the ipset configuration with the following syntax:
|
||||||
//
|
//
|
||||||
// DOMAIN[,DOMAIN].../IPSET_NAME[,IPSET_NAME]...
|
// DOMAIN[,DOMAIN].../IPSET_NAME[,IPSET_NAME]...
|
||||||
//
|
//
|
||||||
// IpsetList must not contain any blank lines or comments.
|
// Lines must not contain any blank lines or comments.
|
||||||
IpsetList []string
|
Lines []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewManager returns a new ipset manager. IPv4 addresses are added to an ipset
|
// NewManager returns a new ipset manager. IPv4 addresses are added to an ipset
|
||||||
// with an ipv4 family; IPv6 addresses, to an ipv6 ipset. ipset must exist.
|
// with an ipv4 family; IPv6 addresses, to an ipv6 ipset. ipset must exist.
|
||||||
//
|
//
|
||||||
// If conf.IpsetList is empty, mgr and err are nil. The error's chain contains
|
// If conf.Lines is empty, mgr and err are nil. The error's chain contains
|
||||||
// [errors.ErrUnsupported] if current OS is not supported.
|
// [errors.ErrUnsupported] if current OS is not supported.
|
||||||
func NewManager(conf *Config) (mgr Manager, err error) {
|
func NewManager(ctx context.Context, conf *Config) (mgr Manager, err error) {
|
||||||
if len(conf.IpsetList) == 0 {
|
if len(conf.Lines) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return newManager(conf)
|
return newManager(ctx, conf)
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,8 @@ import (
|
||||||
// resolved IP addresses.
|
// resolved IP addresses.
|
||||||
|
|
||||||
// newManager returns a new Linux ipset manager.
|
// newManager returns a new Linux ipset manager.
|
||||||
func newManager(conf *Config) (set Manager, err error) {
|
func newManager(ctx context.Context, conf *Config) (set Manager, err error) {
|
||||||
return newManagerWithDialer(conf, defaultDial)
|
return newManagerWithDialer(ctx, conf, defaultDial)
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultDial is the default netfilter dialing function.
|
// defaultDial is the default netfilter dialing function.
|
||||||
|
@ -258,7 +258,7 @@ func parseIpsetConfigLine(confStr string) (hosts, ipsetNames []string, err error
|
||||||
|
|
||||||
// parseIpsetConfig parses the ipset configuration and stores ipsets. It
|
// parseIpsetConfig parses the ipset configuration and stores ipsets. It
|
||||||
// returns an error if the configuration can't be used.
|
// returns an error if the configuration can't be used.
|
||||||
func (m *manager) parseIpsetConfig(ipsetConf []string) (err error) {
|
func (m *manager) parseIpsetConfig(ctx context.Context, ipsetConf []string) (err error) {
|
||||||
// The family doesn't seem to matter when we use a header query, so query
|
// The family doesn't seem to matter when we use a header query, so query
|
||||||
// only the IPv4 one.
|
// only the IPv4 one.
|
||||||
//
|
//
|
||||||
|
@ -282,7 +282,7 @@ func (m *manager) parseIpsetConfig(ipsetConf []string) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var ipsets []props
|
var ipsets []props
|
||||||
ipsets, err = m.ipsets(ipsetNames, currentlyKnown)
|
ipsets, err = m.ipsets(ctx, ipsetNames, currentlyKnown)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getting ipsets from config line at idx %d: %w", i, err)
|
return fmt.Errorf("getting ipsets from config line at idx %d: %w", i, err)
|
||||||
}
|
}
|
||||||
|
@ -332,7 +332,11 @@ func (m *manager) ipsetProps(name string) (p props, err error) {
|
||||||
|
|
||||||
// ipsets returns ipset properties of currently known ipsets. It also makes an
|
// ipsets returns ipset properties of currently known ipsets. It also makes an
|
||||||
// additional ipset header data query if needed.
|
// additional ipset header data query if needed.
|
||||||
func (m *manager) ipsets(names []string, currentlyKnown map[string]props) (sets []props, err error) {
|
func (m *manager) ipsets(
|
||||||
|
ctx context.Context,
|
||||||
|
names []string,
|
||||||
|
currentlyKnown map[string]props,
|
||||||
|
) (sets []props, err error) {
|
||||||
for _, n := range names {
|
for _, n := range names {
|
||||||
p, ok := currentlyKnown[n]
|
p, ok := currentlyKnown[n]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -340,7 +344,8 @@ func (m *manager) ipsets(names []string, currentlyKnown map[string]props) (sets
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.family != netfilter.ProtoIPv4 && p.family != netfilter.ProtoIPv6 {
|
if p.family != netfilter.ProtoIPv4 && p.family != netfilter.ProtoIPv6 {
|
||||||
m.logger.Debug(
|
m.logger.DebugContext(
|
||||||
|
ctx,
|
||||||
"got unexpected ipset family while getting set properties",
|
"got unexpected ipset family while getting set properties",
|
||||||
"set_name", p.name,
|
"set_name", p.name,
|
||||||
"set_type", p.typeName,
|
"set_type", p.typeName,
|
||||||
|
@ -362,7 +367,7 @@ func (m *manager) ipsets(names []string, currentlyKnown map[string]props) (sets
|
||||||
|
|
||||||
// newManagerWithDialer returns a new Linux ipset manager using the provided
|
// newManagerWithDialer returns a new Linux ipset manager using the provided
|
||||||
// dialer.
|
// dialer.
|
||||||
func newManagerWithDialer(conf *Config, dial dialer) (mgr Manager, err error) {
|
func newManagerWithDialer(ctx context.Context, conf *Config, dial dialer) (mgr Manager, err error) {
|
||||||
defer func() { err = errors.Annotate(err, "ipset: %w") }()
|
defer func() { err = errors.Annotate(err, "ipset: %w") }()
|
||||||
|
|
||||||
m := &manager{
|
m := &manager{
|
||||||
|
@ -383,7 +388,7 @@ func newManagerWithDialer(conf *Config, dial dialer) (mgr Manager, err error) {
|
||||||
if errors.Is(err, unix.EPROTONOSUPPORT) {
|
if errors.Is(err, unix.EPROTONOSUPPORT) {
|
||||||
// The implementation doesn't support this protocol version. Just
|
// The implementation doesn't support this protocol version. Just
|
||||||
// issue a warning.
|
// issue a warning.
|
||||||
m.logger.Warn("dialing netfilter", slogutil.KeyError, err)
|
m.logger.WarnContext(ctx, "dialing netfilter", slogutil.KeyError, err)
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -391,12 +396,12 @@ func newManagerWithDialer(conf *Config, dial dialer) (mgr Manager, err error) {
|
||||||
return nil, fmt.Errorf("dialing netfilter: %w", err)
|
return nil, fmt.Errorf("dialing netfilter: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.parseIpsetConfig(conf.IpsetList)
|
err = m.parseIpsetConfig(ctx, conf.Lines)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("getting ipsets: %w", err)
|
return nil, fmt.Errorf("getting ipsets: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.logger.Debug("initialized")
|
m.logger.DebugContext(ctx, "initialized")
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,10 +96,10 @@ func TestManager_Add(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
conf := &Config{
|
conf := &Config{
|
||||||
Logger: slogutil.NewDiscardLogger(),
|
Logger: slogutil.NewDiscardLogger(),
|
||||||
IpsetList: ipsetList,
|
Lines: ipsetList,
|
||||||
}
|
}
|
||||||
m, err := newManagerWithDialer(conf, fakeDial)
|
m, err := newManagerWithDialer(testutil.ContextWithTimeout(t, testTimeout), conf, fakeDial)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ip4 := net.IP{1, 2, 3, 4}
|
ip4 := net.IP{1, 2, 3, 4}
|
||||||
|
|
|
@ -3,9 +3,11 @@
|
||||||
package ipset
|
package ipset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newManager(_ *Config) (mgr Manager, err error) {
|
func newManager(_ context.Context, _ *Config) (mgr Manager, err error) {
|
||||||
return nil, aghos.Unsupported("ipset")
|
return nil, aghos.Unsupported("ipset")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue