github.com/TeaOSLab/EdgeNode@v1.3.8/internal/firewalls/nftables/chain.go (about)

     1  // Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
     2  //go:build linux
     3  
     4  package nftables
     5  
     6  import (
     7  	"bytes"
     8  	"errors"
     9  	nft "github.com/google/nftables"
    10  	"github.com/google/nftables/expr"
    11  )
    12  
    13  const MaxChainNameLength = 31
    14  
    15  type RuleOptions struct {
    16  	Exprs    []expr.Any
    17  	UserData []byte
    18  }
    19  
    20  // Chain chain object in table
    21  type Chain struct {
    22  	conn     *Conn
    23  	rawTable *nft.Table
    24  	rawChain *nft.Chain
    25  }
    26  
    27  func NewChain(conn *Conn, rawTable *nft.Table, rawChain *nft.Chain) *Chain {
    28  	return &Chain{
    29  		conn:     conn,
    30  		rawTable: rawTable,
    31  		rawChain: rawChain,
    32  	}
    33  }
    34  
    35  func (this *Chain) Raw() *nft.Chain {
    36  	return this.rawChain
    37  }
    38  
    39  func (this *Chain) Name() string {
    40  	return this.rawChain.Name
    41  }
    42  
    43  func (this *Chain) AddRule(options *RuleOptions) (*Rule, error) {
    44  	var rawRule = this.conn.Raw().AddRule(&nft.Rule{
    45  		Table:    this.rawTable,
    46  		Chain:    this.rawChain,
    47  		Exprs:    options.Exprs,
    48  		UserData: options.UserData,
    49  	})
    50  	err := this.conn.Commit()
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	return NewRule(rawRule), nil
    55  }
    56  
    57  func (this *Chain) AddAcceptIPv4Rule(ip []byte, userData []byte) (*Rule, error) {
    58  	return this.AddRule(&RuleOptions{
    59  		Exprs: []expr.Any{
    60  			&expr.Payload{
    61  				DestRegister: 1,
    62  				Base:         expr.PayloadBaseNetworkHeader,
    63  				Offset:       12,
    64  				Len:          4,
    65  			},
    66  			&expr.Cmp{
    67  				Op:       expr.CmpOpEq,
    68  				Register: 1,
    69  				Data:     ip,
    70  			},
    71  			&expr.Verdict{
    72  				Kind: expr.VerdictAccept,
    73  			},
    74  		},
    75  		UserData: userData,
    76  	})
    77  }
    78  
    79  func (this *Chain) AddAcceptIPv6Rule(ip []byte, userData []byte) (*Rule, error) {
    80  	return this.AddRule(&RuleOptions{
    81  		Exprs: []expr.Any{
    82  			&expr.Payload{
    83  				DestRegister: 1,
    84  				Base:         expr.PayloadBaseNetworkHeader,
    85  				Offset:       8,
    86  				Len:          16,
    87  			},
    88  			&expr.Cmp{
    89  				Op:       expr.CmpOpEq,
    90  				Register: 1,
    91  				Data:     ip,
    92  			},
    93  			&expr.Verdict{
    94  				Kind: expr.VerdictAccept,
    95  			},
    96  		},
    97  		UserData: userData,
    98  	})
    99  }
   100  
   101  func (this *Chain) AddDropIPv4Rule(ip []byte, userData []byte) (*Rule, error) {
   102  	return this.AddRule(&RuleOptions{
   103  		Exprs: []expr.Any{
   104  			&expr.Payload{
   105  				DestRegister: 1,
   106  				Base:         expr.PayloadBaseNetworkHeader,
   107  				Offset:       12,
   108  				Len:          4,
   109  			},
   110  			&expr.Cmp{
   111  				Op:       expr.CmpOpEq,
   112  				Register: 1,
   113  				Data:     ip,
   114  			},
   115  			&expr.Verdict{
   116  				Kind: expr.VerdictDrop,
   117  			},
   118  		},
   119  		UserData: userData,
   120  	})
   121  }
   122  
   123  func (this *Chain) AddDropIPv6Rule(ip []byte, userData []byte) (*Rule, error) {
   124  	return this.AddRule(&RuleOptions{
   125  		Exprs: []expr.Any{
   126  			&expr.Payload{
   127  				DestRegister: 1,
   128  				Base:         expr.PayloadBaseNetworkHeader,
   129  				Offset:       8,
   130  				Len:          16,
   131  			},
   132  			&expr.Cmp{
   133  				Op:       expr.CmpOpEq,
   134  				Register: 1,
   135  				Data:     ip,
   136  			},
   137  			&expr.Verdict{
   138  				Kind: expr.VerdictDrop,
   139  			},
   140  		},
   141  		UserData: userData,
   142  	})
   143  }
   144  
   145  func (this *Chain) AddRejectIPv4Rule(ip []byte, userData []byte) (*Rule, error) {
   146  	return this.AddRule(&RuleOptions{
   147  		Exprs: []expr.Any{
   148  			&expr.Payload{
   149  				DestRegister: 1,
   150  				Base:         expr.PayloadBaseNetworkHeader,
   151  				Offset:       12,
   152  				Len:          4,
   153  			},
   154  			&expr.Cmp{
   155  				Op:       expr.CmpOpEq,
   156  				Register: 1,
   157  				Data:     ip,
   158  			},
   159  			&expr.Reject{},
   160  		},
   161  		UserData: userData,
   162  	})
   163  }
   164  
   165  func (this *Chain) AddRejectIPv6Rule(ip []byte, userData []byte) (*Rule, error) {
   166  	return this.AddRule(&RuleOptions{
   167  		Exprs: []expr.Any{
   168  			&expr.Payload{
   169  				DestRegister: 1,
   170  				Base:         expr.PayloadBaseNetworkHeader,
   171  				Offset:       8,
   172  				Len:          16,
   173  			},
   174  			&expr.Cmp{
   175  				Op:       expr.CmpOpEq,
   176  				Register: 1,
   177  				Data:     ip,
   178  			},
   179  			&expr.Reject{},
   180  		},
   181  		UserData: userData,
   182  	})
   183  }
   184  
   185  func (this *Chain) AddAcceptIPv4SetRule(setName string, userData []byte) (*Rule, error) {
   186  	return this.AddRule(&RuleOptions{
   187  		Exprs: []expr.Any{
   188  			&expr.Payload{
   189  				DestRegister: 1,
   190  				Base:         expr.PayloadBaseNetworkHeader,
   191  				Offset:       12,
   192  				Len:          4,
   193  			},
   194  			&expr.Lookup{
   195  				SourceRegister: 1,
   196  				SetName:        setName,
   197  			},
   198  			&expr.Verdict{
   199  				Kind: expr.VerdictAccept,
   200  			},
   201  		},
   202  		UserData: userData,
   203  	})
   204  }
   205  
   206  func (this *Chain) AddAcceptIPv6SetRule(setName string, userData []byte) (*Rule, error) {
   207  	return this.AddRule(&RuleOptions{
   208  		Exprs: []expr.Any{
   209  			&expr.Payload{
   210  				DestRegister: 1,
   211  				Base:         expr.PayloadBaseNetworkHeader,
   212  				Offset:       8,
   213  				Len:          16,
   214  			},
   215  			&expr.Lookup{
   216  				SourceRegister: 1,
   217  				SetName:        setName,
   218  			},
   219  			&expr.Verdict{
   220  				Kind: expr.VerdictAccept,
   221  			},
   222  		},
   223  		UserData: userData,
   224  	})
   225  }
   226  
   227  func (this *Chain) AddDropIPv4SetRule(setName string, userData []byte) (*Rule, error) {
   228  	return this.AddRule(&RuleOptions{
   229  		Exprs: []expr.Any{
   230  			&expr.Payload{
   231  				DestRegister: 1,
   232  				Base:         expr.PayloadBaseNetworkHeader,
   233  				Offset:       12,
   234  				Len:          4,
   235  			},
   236  			&expr.Lookup{
   237  				SourceRegister: 1,
   238  				SetName:        setName,
   239  			},
   240  			&expr.Verdict{
   241  				Kind: expr.VerdictDrop,
   242  			},
   243  		},
   244  		UserData: userData,
   245  	})
   246  }
   247  
   248  func (this *Chain) AddDropIPv6SetRule(setName string, userData []byte) (*Rule, error) {
   249  	return this.AddRule(&RuleOptions{
   250  		Exprs: []expr.Any{
   251  			&expr.Payload{
   252  				DestRegister: 1,
   253  				Base:         expr.PayloadBaseNetworkHeader,
   254  				Offset:       8,
   255  				Len:          16,
   256  			},
   257  			&expr.Lookup{
   258  				SourceRegister: 1,
   259  				SetName:        setName,
   260  			},
   261  			&expr.Verdict{
   262  				Kind: expr.VerdictDrop,
   263  			},
   264  		},
   265  		UserData: userData,
   266  	})
   267  }
   268  
   269  func (this *Chain) AddRejectIPv4SetRule(setName string, userData []byte) (*Rule, error) {
   270  	return this.AddRule(&RuleOptions{
   271  		Exprs: []expr.Any{
   272  			&expr.Payload{
   273  				DestRegister: 1,
   274  				Base:         expr.PayloadBaseNetworkHeader,
   275  				Offset:       12,
   276  				Len:          4,
   277  			},
   278  			&expr.Lookup{
   279  				SourceRegister: 1,
   280  				SetName:        setName,
   281  			},
   282  			&expr.Reject{},
   283  		},
   284  		UserData: userData,
   285  	})
   286  }
   287  
   288  func (this *Chain) AddRejectIPv6SetRule(setName string, userData []byte) (*Rule, error) {
   289  	return this.AddRule(&RuleOptions{
   290  		Exprs: []expr.Any{
   291  			&expr.Payload{
   292  				DestRegister: 1,
   293  				Base:         expr.PayloadBaseNetworkHeader,
   294  				Offset:       8,
   295  				Len:          16,
   296  			},
   297  			&expr.Lookup{
   298  				SourceRegister: 1,
   299  				SetName:        setName,
   300  			},
   301  			&expr.Reject{},
   302  		},
   303  		UserData: userData,
   304  	})
   305  }
   306  
   307  func (this *Chain) AddAcceptInterfaceRule(interfaceName string, userData []byte) (*Rule, error) {
   308  	if len(interfaceName) >= 16 {
   309  		return nil, errors.New("invalid interface name '" + interfaceName + "'")
   310  	}
   311  	var ifname = make([]byte, 16)
   312  	copy(ifname, interfaceName+"\x00")
   313  
   314  	return this.AddRule(&RuleOptions{
   315  		Exprs: []expr.Any{
   316  			&expr.Meta{
   317  				Key:      expr.MetaKeyIIFNAME,
   318  				Register: 1,
   319  			},
   320  			&expr.Cmp{
   321  				Op:       expr.CmpOpEq,
   322  				Register: 1,
   323  				Data:     ifname,
   324  			},
   325  			&expr.Verdict{
   326  				Kind: expr.VerdictAccept,
   327  			},
   328  		},
   329  		UserData: userData,
   330  	})
   331  }
   332  
   333  func (this *Chain) GetRuleWithUserData(userData []byte) (*Rule, error) {
   334  	rawRules, err := this.conn.Raw().GetRule(this.rawTable, this.rawChain)
   335  	if err != nil {
   336  		return nil, err
   337  	}
   338  	for _, rawRule := range rawRules {
   339  		if bytes.Compare(rawRule.UserData, userData) == 0 {
   340  			return NewRule(rawRule), nil
   341  		}
   342  	}
   343  	return nil, ErrRuleNotFound
   344  }
   345  
   346  func (this *Chain) GetRules() ([]*Rule, error) {
   347  	rawRules, err := this.conn.Raw().GetRule(this.rawTable, this.rawChain)
   348  	if err != nil {
   349  		return nil, err
   350  	}
   351  	var result = []*Rule{}
   352  	for _, rawRule := range rawRules {
   353  		result = append(result, NewRule(rawRule))
   354  	}
   355  	return result, nil
   356  }
   357  
   358  func (this *Chain) DeleteRule(rule *Rule) error {
   359  	err := this.conn.Raw().DelRule(rule.Raw())
   360  	if err != nil {
   361  		return err
   362  	}
   363  	return this.conn.Commit()
   364  }
   365  
   366  func (this *Chain) Flush() error {
   367  	this.conn.Raw().FlushChain(this.rawChain)
   368  	return this.conn.Commit()
   369  }