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