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 }