conntrack.go 2.1 KB

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