github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/iptables/conntrack.go (about)

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