conntrack.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. //go:build linux
  2. // +build linux
  3. package iptables
  4. import (
  5. "errors"
  6. "net"
  7. "syscall"
  8. "github.com/sirupsen/logrus"
  9. "github.com/vishvananda/netlink"
  10. )
  11. var (
  12. // ErrConntrackNotConfigurable means that conntrack module is not loaded or does not have the netlink module loaded
  13. ErrConntrackNotConfigurable = errors.New("conntrack is not available")
  14. )
  15. // IsConntrackProgrammable returns true if the handle supports the NETLINK_NETFILTER and the base modules are loaded
  16. func IsConntrackProgrammable(nlh *netlink.Handle) bool {
  17. return nlh.SupportsNetlinkFamily(syscall.NETLINK_NETFILTER)
  18. }
  19. // DeleteConntrackEntries deletes all the conntrack connections on the host for the specified IP
  20. // Returns the number of flows deleted for IPv4, IPv6 else error
  21. func DeleteConntrackEntries(nlh *netlink.Handle, ipv4List []net.IP, ipv6List []net.IP) (uint, uint, error) {
  22. if !IsConntrackProgrammable(nlh) {
  23. return 0, 0, ErrConntrackNotConfigurable
  24. }
  25. var totalIPv4FlowPurged uint
  26. for _, ipAddress := range ipv4List {
  27. flowPurged, err := purgeConntrackState(nlh, syscall.AF_INET, ipAddress)
  28. if err != nil {
  29. logrus.Warnf("Failed to delete conntrack state for %s: %v", ipAddress, err)
  30. continue
  31. }
  32. totalIPv4FlowPurged += flowPurged
  33. }
  34. var totalIPv6FlowPurged uint
  35. for _, ipAddress := range ipv6List {
  36. flowPurged, err := purgeConntrackState(nlh, syscall.AF_INET6, ipAddress)
  37. if err != nil {
  38. logrus.Warnf("Failed to delete conntrack state for %s: %v", ipAddress, err)
  39. continue
  40. }
  41. totalIPv6FlowPurged += flowPurged
  42. }
  43. logrus.Debugf("DeleteConntrackEntries purged ipv4:%d, ipv6:%d", totalIPv4FlowPurged, totalIPv6FlowPurged)
  44. return totalIPv4FlowPurged, totalIPv6FlowPurged, nil
  45. }
  46. func purgeConntrackState(nlh *netlink.Handle, family netlink.InetFamily, ipAddress net.IP) (uint, error) {
  47. filter := &netlink.ConntrackFilter{}
  48. // NOTE: doing the flush using the ipAddress is safe because today there cannot be multiple networks with the same subnet
  49. // so it will not be possible to flush flows that are of other containers
  50. if err := filter.AddIP(netlink.ConntrackNatAnyIP, ipAddress); err != nil {
  51. return 0, err
  52. }
  53. return nlh.ConntrackDeleteFilter(netlink.ConntrackTable, family, filter)
  54. }