github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/libnetwork/iptables/conntrack.go (about) 1 //go:build linux 2 // +build linux 3 4 package iptables 5 6 import ( 7 "errors" 8 "net" 9 "syscall" 10 11 "github.com/docker/docker/libnetwork/types" 12 "github.com/sirupsen/logrus" 13 "github.com/vishvananda/netlink" 14 ) 15 16 var ( 17 // ErrConntrackNotConfigurable means that conntrack module is not loaded or does not have the netlink module loaded 18 ErrConntrackNotConfigurable = errors.New("conntrack is not available") 19 ) 20 21 // IsConntrackProgrammable returns true if the handle supports the NETLINK_NETFILTER and the base modules are loaded 22 func IsConntrackProgrammable(nlh *netlink.Handle) bool { 23 return nlh.SupportsNetlinkFamily(syscall.NETLINK_NETFILTER) 24 } 25 26 // DeleteConntrackEntries deletes all the conntrack connections on the host for the specified IP 27 // Returns the number of flows deleted for IPv4, IPv6 else error 28 func DeleteConntrackEntries(nlh *netlink.Handle, ipv4List []net.IP, ipv6List []net.IP) (uint, uint, error) { 29 if !IsConntrackProgrammable(nlh) { 30 return 0, 0, ErrConntrackNotConfigurable 31 } 32 33 var totalIPv4FlowPurged uint 34 for _, ipAddress := range ipv4List { 35 flowPurged, err := purgeConntrackState(nlh, syscall.AF_INET, ipAddress) 36 if err != nil { 37 logrus.Warnf("Failed to delete conntrack state for %s: %v", ipAddress, err) 38 continue 39 } 40 totalIPv4FlowPurged += flowPurged 41 } 42 43 var totalIPv6FlowPurged uint 44 for _, ipAddress := range ipv6List { 45 flowPurged, err := purgeConntrackState(nlh, syscall.AF_INET6, ipAddress) 46 if err != nil { 47 logrus.Warnf("Failed to delete conntrack state for %s: %v", ipAddress, err) 48 continue 49 } 50 totalIPv6FlowPurged += flowPurged 51 } 52 53 logrus.Debugf("DeleteConntrackEntries purged ipv4:%d, ipv6:%d", totalIPv4FlowPurged, totalIPv6FlowPurged) 54 return totalIPv4FlowPurged, totalIPv6FlowPurged, nil 55 } 56 57 func DeleteConntrackEntriesByPort(nlh *netlink.Handle, proto types.Protocol, ports []uint16) error { 58 if !IsConntrackProgrammable(nlh) { 59 return ErrConntrackNotConfigurable 60 } 61 62 var totalIPv4FlowPurged uint 63 var totalIPv6FlowPurged uint 64 65 for _, port := range ports { 66 filter := &netlink.ConntrackFilter{} 67 if err := filter.AddProtocol(uint8(proto)); err != nil { 68 logrus.Warnf("Failed to delete conntrack state for %s port %d: %v", proto.String(), port, err) 69 continue 70 } 71 if err := filter.AddPort(netlink.ConntrackOrigDstPort, port); err != nil { 72 logrus.Warnf("Failed to delete conntrack state for %s port %d: %v", proto.String(), port, err) 73 continue 74 } 75 76 v4FlowPurged, err := nlh.ConntrackDeleteFilter(netlink.ConntrackTable, syscall.AF_INET, filter) 77 if err != nil { 78 logrus.Warnf("Failed to delete conntrack state for IPv4 %s port %d: %v", proto.String(), port, err) 79 } 80 totalIPv4FlowPurged += v4FlowPurged 81 82 v6FlowPurged, err := nlh.ConntrackDeleteFilter(netlink.ConntrackTable, syscall.AF_INET6, filter) 83 if err != nil { 84 logrus.Warnf("Failed to delete conntrack state for IPv6 %s port %d: %v", proto.String(), port, err) 85 } 86 totalIPv6FlowPurged += v6FlowPurged 87 } 88 89 logrus.Debugf("DeleteConntrackEntriesByPort for %s ports purged ipv4:%d, ipv6:%d", proto.String(), totalIPv4FlowPurged, totalIPv6FlowPurged) 90 return nil 91 } 92 93 func purgeConntrackState(nlh *netlink.Handle, family netlink.InetFamily, ipAddress net.IP) (uint, error) { 94 filter := &netlink.ConntrackFilter{} 95 // NOTE: doing the flush using the ipAddress is safe because today there cannot be multiple networks with the same subnet 96 // so it will not be possible to flush flows that are of other containers 97 if err := filter.AddIP(netlink.ConntrackNatAnyIP, ipAddress); err != nil { 98 return 0, err 99 } 100 return nlh.ConntrackDeleteFilter(netlink.ConntrackTable, family, filter) 101 }