packet.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package firewall
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/netip"
  6. )
  7. type m = map[string]any
  8. const (
  9. ProtoAny = 0 // When we want to handle HOPOPT (0) we can change this, if ever
  10. ProtoTCP = 6
  11. ProtoUDP = 17
  12. ProtoICMP = 1
  13. ProtoICMPv6 = 58
  14. PortAny = 0 // Special value for matching `port: any`
  15. PortFragment = -1 // Special value for matching `port: fragment`
  16. )
  17. type Packet struct {
  18. LocalAddr netip.Addr
  19. RemoteAddr netip.Addr
  20. // LocalPort is the destination port for incoming traffic, or the source port for outgoing. Zero for ICMP.
  21. LocalPort uint16
  22. // RemotePort is the source port for incoming traffic, or the destination port for outgoing.
  23. // For ICMP, it's the "identifier". This is only used for connection tracking, actual firewall rules will not filter on ICMP identifier
  24. RemotePort uint16
  25. Protocol uint8
  26. Fragment bool
  27. }
  28. // PacketContext carries additional parsed details about a packet that are
  29. // useful for event reporting but deliberately kept out of Packet so Packet
  30. // can keep being used as a conntrack map key. Populated alongside Packet by
  31. // newPacket.
  32. //
  33. // Fields are interpreted based on Packet.Protocol:
  34. // - ProtoTCP: TCPFlags is meaningful; ICMPType / ICMPCode are zero
  35. // - ProtoICMP, ProtoICMPv6: ICMPType / ICMPCode are meaningful; TCPFlags is zero
  36. // - ProtoUDP and others: only Length is meaningful
  37. type PacketContext struct {
  38. // Length is the total IP packet length in bytes, including headers.
  39. Length uint16
  40. // TCPFlags is the flag byte from the TCP header (bits for FIN, SYN, RST,
  41. // PSH, ACK, URG, ECE, CWR).
  42. TCPFlags uint8
  43. // ICMPType is the type field of the ICMP / ICMPv6 header.
  44. ICMPType uint8
  45. // ICMPCode is the code field of the ICMP / ICMPv6 header.
  46. ICMPCode uint8
  47. }
  48. func (fp *Packet) Copy() *Packet {
  49. return &Packet{
  50. LocalAddr: fp.LocalAddr,
  51. RemoteAddr: fp.RemoteAddr,
  52. LocalPort: fp.LocalPort,
  53. RemotePort: fp.RemotePort,
  54. Protocol: fp.Protocol,
  55. Fragment: fp.Fragment,
  56. }
  57. }
  58. func (fp Packet) MarshalJSON() ([]byte, error) {
  59. var proto string
  60. switch fp.Protocol {
  61. case ProtoTCP:
  62. proto = "tcp"
  63. case ProtoICMP:
  64. proto = "icmp"
  65. case ProtoICMPv6:
  66. proto = "icmpv6"
  67. case ProtoUDP:
  68. proto = "udp"
  69. default:
  70. proto = fmt.Sprintf("unknown %v", fp.Protocol)
  71. }
  72. return json.Marshal(m{
  73. "LocalAddr": fp.LocalAddr.String(),
  74. "RemoteAddr": fp.RemoteAddr.String(),
  75. "LocalPort": fp.LocalPort,
  76. "RemotePort": fp.RemotePort,
  77. "Protocol": proto,
  78. "Fragment": fp.Fragment,
  79. })
  80. }