expr.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. // Copyright 2018 Google LLC. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Package expr provides nftables rule expressions.
  15. package expr
  16. import (
  17. "encoding/binary"
  18. "github.com/google/nftables/binaryutil"
  19. "github.com/google/nftables/internal/parseexprfunc"
  20. "github.com/mdlayher/netlink"
  21. "golang.org/x/sys/unix"
  22. )
  23. func init() {
  24. parseexprfunc.ParseExprBytesFunc = func(fam byte, ad *netlink.AttributeDecoder, b []byte) ([]interface{}, error) {
  25. exprs, err := exprsFromBytes(fam, ad, b)
  26. if err != nil {
  27. return nil, err
  28. }
  29. result := make([]interface{}, len(exprs))
  30. for idx, expr := range exprs {
  31. result[idx] = expr
  32. }
  33. return result, nil
  34. }
  35. parseexprfunc.ParseExprMsgFunc = func(fam byte, b []byte) ([]interface{}, error) {
  36. ad, err := netlink.NewAttributeDecoder(b)
  37. if err != nil {
  38. return nil, err
  39. }
  40. ad.ByteOrder = binary.BigEndian
  41. var exprs []interface{}
  42. for ad.Next() {
  43. e, err := parseexprfunc.ParseExprBytesFunc(fam, ad, b)
  44. if err != nil {
  45. return e, err
  46. }
  47. exprs = append(exprs, e...)
  48. }
  49. return exprs, ad.Err()
  50. }
  51. }
  52. // Marshal serializes the specified expression into a byte slice.
  53. func Marshal(fam byte, e Any) ([]byte, error) {
  54. return e.marshal(fam)
  55. }
  56. // Unmarshal fills an expression from the specified byte slice.
  57. func Unmarshal(fam byte, data []byte, e Any) error {
  58. return e.unmarshal(fam, data)
  59. }
  60. // exprsFromBytes parses nested raw expressions bytes
  61. // to construct nftables expressions
  62. func exprsFromBytes(fam byte, ad *netlink.AttributeDecoder, b []byte) ([]Any, error) {
  63. var exprs []Any
  64. ad.Do(func(b []byte) error {
  65. ad, err := netlink.NewAttributeDecoder(b)
  66. if err != nil {
  67. return err
  68. }
  69. ad.ByteOrder = binary.BigEndian
  70. var name string
  71. for ad.Next() {
  72. switch ad.Type() {
  73. case unix.NFTA_EXPR_NAME:
  74. name = ad.String()
  75. if name == "notrack" {
  76. e := &Notrack{}
  77. exprs = append(exprs, e)
  78. }
  79. case unix.NFTA_EXPR_DATA:
  80. var e Any
  81. switch name {
  82. case "ct":
  83. e = &Ct{}
  84. case "range":
  85. e = &Range{}
  86. case "meta":
  87. e = &Meta{}
  88. case "cmp":
  89. e = &Cmp{}
  90. case "counter":
  91. e = &Counter{}
  92. case "objref":
  93. e = &Objref{}
  94. case "payload":
  95. e = &Payload{}
  96. case "lookup":
  97. e = &Lookup{}
  98. case "immediate":
  99. e = &Immediate{}
  100. case "bitwise":
  101. e = &Bitwise{}
  102. case "redir":
  103. e = &Redir{}
  104. case "nat":
  105. e = &NAT{}
  106. case "limit":
  107. e = &Limit{}
  108. case "quota":
  109. e = &Quota{}
  110. case "dynset":
  111. e = &Dynset{}
  112. case "log":
  113. e = &Log{}
  114. case "exthdr":
  115. e = &Exthdr{}
  116. case "match":
  117. e = &Match{}
  118. case "target":
  119. e = &Target{}
  120. case "connlimit":
  121. e = &Connlimit{}
  122. case "queue":
  123. e = &Queue{}
  124. case "flow_offload":
  125. e = &FlowOffload{}
  126. case "reject":
  127. e = &Reject{}
  128. case "masq":
  129. e = &Masq{}
  130. }
  131. if e == nil {
  132. // TODO: introduce an opaque expression type so that users know
  133. // something is here.
  134. continue // unsupported expression type
  135. }
  136. ad.Do(func(b []byte) error {
  137. if err := Unmarshal(fam, b, e); err != nil {
  138. return err
  139. }
  140. // Verdict expressions are a special-case of immediate expressions, so
  141. // if the expression is an immediate writing nothing into the verdict
  142. // register (invalid), re-parse it as a verdict expression.
  143. if imm, isImmediate := e.(*Immediate); isImmediate && imm.Register == unix.NFT_REG_VERDICT && len(imm.Data) == 0 {
  144. e = &Verdict{}
  145. if err := Unmarshal(fam, b, e); err != nil {
  146. return err
  147. }
  148. }
  149. exprs = append(exprs, e)
  150. return nil
  151. })
  152. }
  153. }
  154. return ad.Err()
  155. })
  156. return exprs, ad.Err()
  157. }
  158. // Any is an interface implemented by any expression type.
  159. type Any interface {
  160. marshal(fam byte) ([]byte, error)
  161. unmarshal(fam byte, data []byte) error
  162. }
  163. // MetaKey specifies which piece of meta information should be loaded. See also
  164. // https://wiki.nftables.org/wiki-nftables/index.php/Matching_packet_metainformation
  165. type MetaKey uint32
  166. // Possible MetaKey values.
  167. const (
  168. MetaKeyLEN MetaKey = unix.NFT_META_LEN
  169. MetaKeyPROTOCOL MetaKey = unix.NFT_META_PROTOCOL
  170. MetaKeyPRIORITY MetaKey = unix.NFT_META_PRIORITY
  171. MetaKeyMARK MetaKey = unix.NFT_META_MARK
  172. MetaKeyIIF MetaKey = unix.NFT_META_IIF
  173. MetaKeyOIF MetaKey = unix.NFT_META_OIF
  174. MetaKeyIIFNAME MetaKey = unix.NFT_META_IIFNAME
  175. MetaKeyOIFNAME MetaKey = unix.NFT_META_OIFNAME
  176. MetaKeyIIFTYPE MetaKey = unix.NFT_META_IIFTYPE
  177. MetaKeyOIFTYPE MetaKey = unix.NFT_META_OIFTYPE
  178. MetaKeySKUID MetaKey = unix.NFT_META_SKUID
  179. MetaKeySKGID MetaKey = unix.NFT_META_SKGID
  180. MetaKeyNFTRACE MetaKey = unix.NFT_META_NFTRACE
  181. MetaKeyRTCLASSID MetaKey = unix.NFT_META_RTCLASSID
  182. MetaKeySECMARK MetaKey = unix.NFT_META_SECMARK
  183. MetaKeyNFPROTO MetaKey = unix.NFT_META_NFPROTO
  184. MetaKeyL4PROTO MetaKey = unix.NFT_META_L4PROTO
  185. MetaKeyBRIIIFNAME MetaKey = unix.NFT_META_BRI_IIFNAME
  186. MetaKeyBRIOIFNAME MetaKey = unix.NFT_META_BRI_OIFNAME
  187. MetaKeyPKTTYPE MetaKey = unix.NFT_META_PKTTYPE
  188. MetaKeyCPU MetaKey = unix.NFT_META_CPU
  189. MetaKeyIIFGROUP MetaKey = unix.NFT_META_IIFGROUP
  190. MetaKeyOIFGROUP MetaKey = unix.NFT_META_OIFGROUP
  191. MetaKeyCGROUP MetaKey = unix.NFT_META_CGROUP
  192. MetaKeyPRANDOM MetaKey = unix.NFT_META_PRANDOM
  193. )
  194. // Meta loads packet meta information for later comparisons. See also
  195. // https://wiki.nftables.org/wiki-nftables/index.php/Matching_packet_metainformation
  196. type Meta struct {
  197. Key MetaKey
  198. SourceRegister bool
  199. Register uint32
  200. }
  201. func (e *Meta) marshal(fam byte) ([]byte, error) {
  202. regData := []byte{}
  203. exprData, err := netlink.MarshalAttributes(
  204. []netlink.Attribute{
  205. {Type: unix.NFTA_META_KEY, Data: binaryutil.BigEndian.PutUint32(uint32(e.Key))},
  206. },
  207. )
  208. if err != nil {
  209. return nil, err
  210. }
  211. if e.SourceRegister {
  212. regData, err = netlink.MarshalAttributes(
  213. []netlink.Attribute{
  214. {Type: unix.NFTA_META_SREG, Data: binaryutil.BigEndian.PutUint32(e.Register)},
  215. },
  216. )
  217. } else {
  218. regData, err = netlink.MarshalAttributes(
  219. []netlink.Attribute{
  220. {Type: unix.NFTA_META_DREG, Data: binaryutil.BigEndian.PutUint32(e.Register)},
  221. },
  222. )
  223. }
  224. if err != nil {
  225. return nil, err
  226. }
  227. exprData = append(exprData, regData...)
  228. return netlink.MarshalAttributes([]netlink.Attribute{
  229. {Type: unix.NFTA_EXPR_NAME, Data: []byte("meta\x00")},
  230. {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData},
  231. })
  232. }
  233. func (e *Meta) unmarshal(fam byte, data []byte) error {
  234. ad, err := netlink.NewAttributeDecoder(data)
  235. if err != nil {
  236. return err
  237. }
  238. ad.ByteOrder = binary.BigEndian
  239. for ad.Next() {
  240. switch ad.Type() {
  241. case unix.NFTA_META_SREG:
  242. e.Register = ad.Uint32()
  243. e.SourceRegister = true
  244. case unix.NFTA_META_DREG:
  245. e.Register = ad.Uint32()
  246. case unix.NFTA_META_KEY:
  247. e.Key = MetaKey(ad.Uint32())
  248. }
  249. }
  250. return ad.Err()
  251. }
  252. // Masq (Masquerade) is a special case of SNAT, where the source address is
  253. // automagically set to the address of the output interface. See also
  254. // https://wiki.nftables.org/wiki-nftables/index.php/Performing_Network_Address_Translation_(NAT)#Masquerading
  255. type Masq struct {
  256. Random bool
  257. FullyRandom bool
  258. Persistent bool
  259. ToPorts bool
  260. RegProtoMin uint32
  261. RegProtoMax uint32
  262. }
  263. // TODO, Once the constants below are available in golang.org/x/sys/unix, switch to use those.
  264. const (
  265. // NF_NAT_RANGE_PROTO_RANDOM defines flag for a random masquerade
  266. NF_NAT_RANGE_PROTO_RANDOM = 0x4
  267. // NF_NAT_RANGE_PROTO_RANDOM_FULLY defines flag for a fully random masquerade
  268. NF_NAT_RANGE_PROTO_RANDOM_FULLY = 0x10
  269. // NF_NAT_RANGE_PERSISTENT defines flag for a persistent masquerade
  270. NF_NAT_RANGE_PERSISTENT = 0x8
  271. )
  272. func (e *Masq) marshal(fam byte) ([]byte, error) {
  273. msgData := []byte{}
  274. if !e.ToPorts {
  275. flags := uint32(0)
  276. if e.Random {
  277. flags |= NF_NAT_RANGE_PROTO_RANDOM
  278. }
  279. if e.FullyRandom {
  280. flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY
  281. }
  282. if e.Persistent {
  283. flags |= NF_NAT_RANGE_PERSISTENT
  284. }
  285. if flags != 0 {
  286. flagsData, err := netlink.MarshalAttributes([]netlink.Attribute{
  287. {Type: unix.NFTA_MASQ_FLAGS, Data: binaryutil.BigEndian.PutUint32(flags)}})
  288. if err != nil {
  289. return nil, err
  290. }
  291. msgData = append(msgData, flagsData...)
  292. }
  293. } else {
  294. regsData, err := netlink.MarshalAttributes([]netlink.Attribute{
  295. {Type: unix.NFTA_MASQ_REG_PROTO_MIN, Data: binaryutil.BigEndian.PutUint32(e.RegProtoMin)}})
  296. if err != nil {
  297. return nil, err
  298. }
  299. msgData = append(msgData, regsData...)
  300. if e.RegProtoMax != 0 {
  301. regsData, err := netlink.MarshalAttributes([]netlink.Attribute{
  302. {Type: unix.NFTA_MASQ_REG_PROTO_MAX, Data: binaryutil.BigEndian.PutUint32(e.RegProtoMax)}})
  303. if err != nil {
  304. return nil, err
  305. }
  306. msgData = append(msgData, regsData...)
  307. }
  308. }
  309. return netlink.MarshalAttributes([]netlink.Attribute{
  310. {Type: unix.NFTA_EXPR_NAME, Data: []byte("masq\x00")},
  311. {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: msgData},
  312. })
  313. }
  314. func (e *Masq) unmarshal(fam byte, data []byte) error {
  315. ad, err := netlink.NewAttributeDecoder(data)
  316. if err != nil {
  317. return err
  318. }
  319. ad.ByteOrder = binary.BigEndian
  320. for ad.Next() {
  321. switch ad.Type() {
  322. case unix.NFTA_MASQ_REG_PROTO_MIN:
  323. e.ToPorts = true
  324. e.RegProtoMin = ad.Uint32()
  325. case unix.NFTA_MASQ_REG_PROTO_MAX:
  326. e.RegProtoMax = ad.Uint32()
  327. case unix.NFTA_MASQ_FLAGS:
  328. flags := ad.Uint32()
  329. e.Persistent = (flags & NF_NAT_RANGE_PERSISTENT) != 0
  330. e.Random = (flags & NF_NAT_RANGE_PROTO_RANDOM) != 0
  331. e.FullyRandom = (flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) != 0
  332. }
  333. }
  334. return ad.Err()
  335. }
  336. // CmpOp specifies which type of comparison should be performed.
  337. type CmpOp uint32
  338. // Possible CmpOp values.
  339. const (
  340. CmpOpEq CmpOp = unix.NFT_CMP_EQ
  341. CmpOpNeq CmpOp = unix.NFT_CMP_NEQ
  342. CmpOpLt CmpOp = unix.NFT_CMP_LT
  343. CmpOpLte CmpOp = unix.NFT_CMP_LTE
  344. CmpOpGt CmpOp = unix.NFT_CMP_GT
  345. CmpOpGte CmpOp = unix.NFT_CMP_GTE
  346. )
  347. // Cmp compares a register with the specified data.
  348. type Cmp struct {
  349. Op CmpOp
  350. Register uint32
  351. Data []byte
  352. }
  353. func (e *Cmp) marshal(fam byte) ([]byte, error) {
  354. cmpData, err := netlink.MarshalAttributes([]netlink.Attribute{
  355. {Type: unix.NFTA_DATA_VALUE, Data: e.Data},
  356. })
  357. if err != nil {
  358. return nil, err
  359. }
  360. exprData, err := netlink.MarshalAttributes([]netlink.Attribute{
  361. {Type: unix.NFTA_CMP_SREG, Data: binaryutil.BigEndian.PutUint32(e.Register)},
  362. {Type: unix.NFTA_CMP_OP, Data: binaryutil.BigEndian.PutUint32(uint32(e.Op))},
  363. {Type: unix.NLA_F_NESTED | unix.NFTA_CMP_DATA, Data: cmpData},
  364. })
  365. if err != nil {
  366. return nil, err
  367. }
  368. return netlink.MarshalAttributes([]netlink.Attribute{
  369. {Type: unix.NFTA_EXPR_NAME, Data: []byte("cmp\x00")},
  370. {Type: unix.NLA_F_NESTED | unix.NFTA_EXPR_DATA, Data: exprData},
  371. })
  372. }
  373. func (e *Cmp) unmarshal(fam byte, data []byte) error {
  374. ad, err := netlink.NewAttributeDecoder(data)
  375. if err != nil {
  376. return err
  377. }
  378. ad.ByteOrder = binary.BigEndian
  379. for ad.Next() {
  380. switch ad.Type() {
  381. case unix.NFTA_CMP_SREG:
  382. e.Register = ad.Uint32()
  383. case unix.NFTA_CMP_OP:
  384. e.Op = CmpOp(ad.Uint32())
  385. case unix.NFTA_CMP_DATA:
  386. ad.Do(func(b []byte) error {
  387. ad, err := netlink.NewAttributeDecoder(b)
  388. if err != nil {
  389. return err
  390. }
  391. ad.ByteOrder = binary.BigEndian
  392. if ad.Next() && ad.Type() == unix.NFTA_DATA_VALUE {
  393. ad.Do(func(b []byte) error {
  394. e.Data = b
  395. return nil
  396. })
  397. }
  398. return ad.Err()
  399. })
  400. }
  401. }
  402. return ad.Err()
  403. }