github.com/rawahars/moby@v24.0.4+incompatible/libnetwork/drivers/bridge/setup_bridgenetfiltering.go (about) 1 //go:build linux 2 // +build linux 3 4 package bridge 5 6 import ( 7 "errors" 8 "fmt" 9 "os" 10 "syscall" 11 12 "github.com/sirupsen/logrus" 13 ) 14 15 // Enumeration type saying which versions of IP protocol to process. 16 type ipVersion int 17 18 const ( 19 ipvnone ipVersion = iota 20 ipv4 21 ipv6 22 ipvboth 23 ) 24 25 // getIPVersion gets the IP version in use ( [ipv4], [ipv6] or [ipv4 and ipv6] ) 26 func getIPVersion(config *networkConfiguration) ipVersion { 27 ipVersion := ipv4 28 if config.AddressIPv6 != nil || config.EnableIPv6 { 29 ipVersion |= ipv6 30 } 31 return ipVersion 32 } 33 34 func setupBridgeNetFiltering(config *networkConfiguration, i *bridgeInterface) error { 35 err := checkBridgeNetFiltering(config, i) 36 if err != nil { 37 if ptherr, ok := err.(*os.PathError); ok { 38 if errno, ok := ptherr.Err.(syscall.Errno); ok && errno == syscall.ENOENT { 39 if isRunningInContainer() { 40 logrus.Warnf("running inside docker container, ignoring missing kernel params: %v", err) 41 err = nil 42 } else { 43 err = errors.New("please ensure that br_netfilter kernel module is loaded") 44 } 45 } 46 } 47 if err != nil { 48 return fmt.Errorf("cannot restrict inter-container communication: %v", err) 49 } 50 } 51 return nil 52 } 53 54 // Enable bridge net filtering if ip forwarding is enabled. See github issue #11404 55 func checkBridgeNetFiltering(config *networkConfiguration, i *bridgeInterface) error { 56 ipVer := getIPVersion(config) 57 iface := config.BridgeName 58 doEnable := func(ipVer ipVersion) error { 59 var ipVerName string 60 if ipVer == ipv4 { 61 ipVerName = "IPv4" 62 } else { 63 ipVerName = "IPv6" 64 } 65 enabled, err := isPacketForwardingEnabled(ipVer, iface) 66 if err != nil { 67 logrus.Warnf("failed to check %s forwarding: %v", ipVerName, err) 68 } else if enabled { 69 enabled, err := getKernelBoolParam(getBridgeNFKernelParam(ipVer)) 70 if err != nil || enabled { 71 return err 72 } 73 return setKernelBoolParam(getBridgeNFKernelParam(ipVer), true) 74 } 75 return nil 76 } 77 78 switch ipVer { 79 case ipv4, ipv6: 80 return doEnable(ipVer) 81 case ipvboth: 82 v4err := doEnable(ipv4) 83 v6err := doEnable(ipv6) 84 if v4err == nil { 85 return v6err 86 } 87 return v4err 88 default: 89 return nil 90 } 91 } 92 93 // Get kernel param path saying whether IPv${ipVer} traffic is being forwarded 94 // on particular interface. Interface may be specified for IPv6 only. If 95 // `iface` is empty, `default` will be assumed, which represents default value 96 // for new interfaces. 97 func getForwardingKernelParam(ipVer ipVersion, iface string) string { 98 switch ipVer { 99 case ipv4: 100 return "/proc/sys/net/ipv4/ip_forward" 101 case ipv6: 102 if iface == "" { 103 iface = "default" 104 } 105 return fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/forwarding", iface) 106 default: 107 return "" 108 } 109 } 110 111 // Get kernel param path saying whether bridged IPv${ipVer} traffic shall be 112 // passed to ip${ipVer}tables' chains. 113 func getBridgeNFKernelParam(ipVer ipVersion) string { 114 switch ipVer { 115 case ipv4: 116 return "/proc/sys/net/bridge/bridge-nf-call-iptables" 117 case ipv6: 118 return "/proc/sys/net/bridge/bridge-nf-call-ip6tables" 119 default: 120 return "" 121 } 122 } 123 124 // Gets the value of the kernel parameters located at the given path 125 func getKernelBoolParam(path string) (bool, error) { 126 enabled := false 127 line, err := os.ReadFile(path) 128 if err != nil { 129 return false, err 130 } 131 if len(line) > 0 { 132 enabled = line[0] == '1' 133 } 134 return enabled, err 135 } 136 137 // Sets the value of the kernel parameter located at the given path 138 func setKernelBoolParam(path string, on bool) error { 139 value := byte('0') 140 if on { 141 value = byte('1') 142 } 143 return os.WriteFile(path, []byte{value, '\n'}, 0644) 144 } 145 146 // Checks to see if packet forwarding is enabled 147 func isPacketForwardingEnabled(ipVer ipVersion, iface string) (bool, error) { 148 switch ipVer { 149 case ipv4, ipv6: 150 return getKernelBoolParam(getForwardingKernelParam(ipVer, iface)) 151 case ipvboth: 152 enabled, err := getKernelBoolParam(getForwardingKernelParam(ipv4, "")) 153 if err != nil || !enabled { 154 return enabled, err 155 } 156 return getKernelBoolParam(getForwardingKernelParam(ipv6, iface)) 157 default: 158 return true, nil 159 } 160 } 161 162 func isRunningInContainer() bool { 163 _, err := os.Stat("/.dockerenv") 164 return !os.IsNotExist(err) 165 }