conntrack.go 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. package containers
  2. import (
  3. "github.com/florianl/go-conntrack"
  4. "inet.af/netaddr"
  5. "syscall"
  6. )
  7. var (
  8. conntrackClient *conntrack.Nfct
  9. )
  10. func ConntrackInit() error {
  11. c, err := conntrack.Open(&conntrack.Config{})
  12. if err != nil {
  13. return err
  14. }
  15. conntrackClient = c
  16. return nil
  17. }
  18. func ConntrackGetActualDestination(src, dst netaddr.IPPort) (netaddr.IPPort, error) {
  19. if conntrackClient == nil {
  20. return dst, nil
  21. }
  22. tcp := uint8(syscall.IPPROTO_TCP)
  23. sip := src.IP().IPAddr().IP
  24. dip := dst.IP().IPAddr().IP
  25. sport := src.Port()
  26. dport := dst.Port()
  27. con := conntrack.Con{
  28. Origin: &conntrack.IPTuple{
  29. Src: &sip,
  30. Dst: &dip,
  31. Proto: &conntrack.ProtoTuple{
  32. Number: &tcp,
  33. SrcPort: &sport,
  34. DstPort: &dport,
  35. },
  36. },
  37. }
  38. family := conntrack.IPv4
  39. if dst.IP().Is6() {
  40. family = conntrack.IPv6
  41. }
  42. sessions, err := conntrackClient.Get(conntrack.Conntrack, family, con)
  43. if err != nil {
  44. return netaddr.IPPort{}, err
  45. }
  46. for _, s := range sessions {
  47. if s.Reply != nil && s.Reply.Src != nil && s.Reply.Proto != nil && s.Reply.Proto.SrcPort != nil {
  48. ip, _ := netaddr.FromStdIP(*s.Reply.Src)
  49. port := *s.Reply.Proto.SrcPort
  50. return netaddr.IPPortFrom(ip, port), nil
  51. }
  52. }
  53. return netaddr.IPPort{}, nil
  54. }