Skip to content
Permalink
Browse files Browse the repository at this point in the history
Merge pull request #3801 from weaveworks/disable-accept-ra
Disable accept_ra on Weave Net interfaces
  • Loading branch information
bboreham committed May 22, 2020
2 parents 2f235da + 6ad3e69 commit 15f21f1
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 35 deletions.
26 changes: 15 additions & 11 deletions net/bridge.go
Expand Up @@ -63,10 +63,10 @@ const (
)

type Bridge interface {
init(config *BridgeConfig) error // create and initialise bridge device(s)
attach(veth *netlink.Veth) error // attach veth to bridge
IsFastdp() bool // does this bridge use fastdp?
String() string // human-readable type string
init(procPath string, config *BridgeConfig) error // create and initialise bridge device(s)
attach(veth *netlink.Veth) error // attach veth to bridge
IsFastdp() bool // does this bridge use fastdp?
String() string // human-readable type string
}

// Used to indicate a fallback to the Bridge type
Expand Down Expand Up @@ -250,7 +250,7 @@ func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger, ips
}

for {
if err := bridgeType.init(config); err != nil {
if err := bridgeType.init(procPath, config); err != nil {
if errors.Cause(err) == errBridgeNotSupported {
log.Warnf("Skipping bridge creation of %q due to: %s", bridgeType, err)
bridgeType = bridgeImpl{}
Expand Down Expand Up @@ -279,6 +279,10 @@ func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger, ips
return bridgeType, errors.Wrap(err, "setting proxy_arp")
}
}
// No ipv6 router advertisments please
if err := sysctl(procPath, "net/ipv6/conf/"+config.WeaveBridgeName+"/accept_ra", "0"); err != nil {
return bridgeType, errors.Wrap(err, "setting accept_ra to 0")
}

if err := linkSetUpByName(config.WeaveBridgeName); err != nil {
return bridgeType, err
Expand Down Expand Up @@ -345,11 +349,11 @@ func (b bridgeImpl) initPrep(config *BridgeConfig) error {
return nil
}

func (b bridgeImpl) init(config *BridgeConfig) error {
func (b bridgeImpl) init(procPath string, config *BridgeConfig) error {
if err := b.initPrep(config); err != nil {
return err
}
if _, err := CreateAndAttachVeth(BridgeIfName, PcapIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
if _, err := CreateAndAttachVeth(procPath, BridgeIfName, PcapIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
return netlink.LinkSetUp(veth)
}); err != nil {
return errors.Wrap(err, "creating pcap veth pair")
Expand All @@ -361,7 +365,7 @@ func (b bridgeImpl) init(config *BridgeConfig) error {
return nil
}

func (f fastdpImpl) init(config *BridgeConfig) error {
func (f fastdpImpl) init(procPath string, config *BridgeConfig) error {
odpSupported, err := odp.CreateDatapath(f.datapathName)
if !odpSupported {
msg := ""
Expand Down Expand Up @@ -392,14 +396,14 @@ func (f fastdpImpl) init(config *BridgeConfig) error {
return nil
}

func (bf bridgedFastdpImpl) init(config *BridgeConfig) error {
if err := bf.fastdpImpl.init(config); err != nil {
func (bf bridgedFastdpImpl) init(procPath string, config *BridgeConfig) error {
if err := bf.fastdpImpl.init(procPath, config); err != nil {
return err
}
if err := bf.bridgeImpl.initPrep(config); err != nil {
return err
}
if _, err := CreateAndAttachVeth(BridgeIfName, DatapathIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
if _, err := CreateAndAttachVeth(procPath, BridgeIfName, DatapathIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
if err := netlink.LinkSetUp(veth); err != nil {
return errors.Wrapf(err, "setting link up on %q", veth.Attrs().Name)
}
Expand Down
6 changes: 3 additions & 3 deletions net/netns.go
Expand Up @@ -55,9 +55,9 @@ func WithNetNSByPath(path string, work func() error) error {
}

func NSPathByPid(pid int) string {
return NSPathByPidWithRoot("/", pid)
return NSPathByPidWithProc("/proc", pid)
}

func NSPathByPidWithRoot(root string, pid int) string {
return filepath.Join(root, fmt.Sprintf("/proc/%d/ns/net", pid))
func NSPathByPidWithProc(procPath string, pid int) string {
return filepath.Join(procPath, fmt.Sprint(pid), "/ns/net")
}
25 changes: 17 additions & 8 deletions net/veth.go
Expand Up @@ -13,7 +13,7 @@ import (
)

// create and attach a veth to the Weave bridge
func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, keepTXOn bool, errIfLinkExist bool, init func(peer netlink.Link) error) (*netlink.Veth, error) {
func CreateAndAttachVeth(procPath, name, peerName, bridgeName string, mtu int, keepTXOn bool, errIfLinkExist bool, init func(peer netlink.Link) error) (*netlink.Veth, error) {
bridge, err := netlink.LinkByName(bridgeName)
if err != nil {
return nil, fmt.Errorf(`bridge "%s" not present; did you launch weave?`, bridgeName)
Expand Down Expand Up @@ -49,6 +49,13 @@ func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, keepTXOn bo
if err := bridgeType.attach(veth); err != nil {
return cleanup("attaching veth %q to %q: %s", name, bridgeName, err)
}
// No ipv6 router advertisments please
if err := sysctl(procPath, "net/ipv6/conf/"+name+"/accept_ra", "0"); err != nil {
return cleanup("setting accept_ra to 0: %s", err)
}
if err := sysctl(procPath, "net/ipv6/conf/"+peerName+"/accept_ra", "0"); err != nil {
return cleanup("setting accept_ra to 0: %s", err)
}
if !bridgeType.IsFastdp() && !keepTXOn {
if err := EthtoolTXOff(veth.PeerName); err != nil {
return cleanup(`unable to set tx off on %q: %s`, peerName, err)
Expand Down Expand Up @@ -112,6 +119,9 @@ func interfaceExistsInNamespace(netNSPath string, ifName string) bool {
}

func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool, hairpinMode bool) error {
// AttachContainer expects to be called in host pid namespace
const procPath = "/proc"

ns, err := netns.GetFromPath(netNSPath)
if err != nil {
return err
Expand All @@ -124,12 +134,12 @@ func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMult
id = id[:maxIDLen] // trim passed ID if too long
}
name, peerName := vethPrefix+"pl"+id, vethPrefix+"pg"+id
veth, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, keepTXOn, true, func(veth netlink.Link) error {
veth, err := CreateAndAttachVeth(procPath, name, peerName, bridgeName, mtu, keepTXOn, true, func(veth netlink.Link) error {
if err := netlink.LinkSetNsFd(veth, int(ns)); err != nil {
return fmt.Errorf("failed to move veth to container netns: %s", err)
}
if err := WithNetNS(ns, func() error {
return setupIface(peerName, ifName)
return setupIface(procPath, peerName, ifName)
}); err != nil {
return fmt.Errorf("error setting up interface: %s", err)
}
Expand Down Expand Up @@ -206,7 +216,7 @@ func setupIfaceAddrs(veth netlink.Link, withMulticastRoute bool, cidrs []*net.IP
}

// setupIface expects to be called in the container's netns
func setupIface(ifaceName, newIfName string) error {
func setupIface(procPath, ifaceName, newIfName string) error {
ipt, err := iptables.New()
if err != nil {
return err
Expand All @@ -219,23 +229,22 @@ func setupIface(ifaceName, newIfName string) error {
if err := netlink.LinkSetName(link, newIfName); err != nil {
return err
}
// This is only called by AttachContainer which is only called in host pid namespace
if err := configureARPCache("/proc", newIfName); err != nil {
if err := configureARPCache(procPath, newIfName); err != nil {
return err
}
return ipt.Append("filter", "INPUT", "-i", newIfName, "-d", "224.0.0.0/4", "-j", "DROP")
}

// configureARP is a helper for the Docker plugin which doesn't set the addresses itself
func ConfigureARP(prefix, rootPath string) error {
func ConfigureARP(prefix, procPath string) error {
links, err := netlink.LinkList()
if err != nil {
return err
}
for _, link := range links {
ifName := link.Attrs().Name
if strings.HasPrefix(ifName, prefix) {
configureARPCache(rootPath+"/proc", ifName)
configureARPCache(procPath, ifName)
if addrs, err := netlink.AddrList(link, netlink.FAMILY_V4); err == nil {
for _, addr := range addrs {
arping.GratuitousArpOverIfaceByName(addr.IPNet.IP, ifName)
Expand Down
6 changes: 4 additions & 2 deletions plugin/net/driver.go
Expand Up @@ -39,9 +39,10 @@ type driver struct {
// used only by plugin-v2
forceMulticast bool
networks map[string]network
procPath string
}

func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns, isPluginV2, forceMulticast bool) (skel.Driver, error) {
func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns, isPluginV2, forceMulticast bool, procPath string) (skel.Driver, error) {
driver := &driver{
name: name,
scope: scope,
Expand All @@ -51,6 +52,7 @@ func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns,
// make sure that it's used only by plugin-v2
forceMulticast: isPluginV2 && forceMulticast,
networks: make(map[string]network),
procPath: procPath,
}

// Do not start watcher in the case of plugin v2, which prevents us from
Expand Down Expand Up @@ -134,7 +136,7 @@ func (driver *driver) CreateEndpoint(create *api.CreateEndpointRequest) (*api.Cr

// create veths. note we assume endpoint IDs are unique in the first 9 chars
name, peerName := vethPair(create.EndpointID)
if _, err := weavenet.CreateAndAttachVeth(name, peerName, weavenet.WeaveBridgeName, 0, false, true, nil); err != nil {
if _, err := weavenet.CreateAndAttachVeth(driver.procPath, name, peerName, weavenet.WeaveBridgeName, 0, false, true, nil); err != nil {
return nil, driver.error("JoinEndpoint", "%s", err)
}

Expand Down
9 changes: 2 additions & 7 deletions plugin/net/watcher.go
Expand Up @@ -43,14 +43,9 @@ func (w *watcher) ContainerStarted(id string) {
w.driver.warn("ContainerStarted", "unable to register %s with weaveDNS: %s", id, err)
}
}
rootDir := "/"
if w.driver.isPluginV2 {
// We bind mount host's /proc to /host/proc for plugin-v2
rootDir = "/host"
}
netNSPath := weavenet.NSPathByPidWithRoot(rootDir, info.State.Pid)
netNSPath := weavenet.NSPathByPidWithProc(w.driver.procPath, info.State.Pid)
if err := weavenet.WithNetNSByPath(netNSPath, func() error {
return weavenet.ConfigureARP(weavenet.VethName, rootDir)
return weavenet.ConfigureARP(weavenet.VethName, w.driver.procPath)
}); err != nil {
w.driver.warn("ContainerStarted", "unable to configure interfaces: %s", err)
}
Expand Down
9 changes: 5 additions & 4 deletions plugin/plugin.go
Expand Up @@ -32,6 +32,7 @@ type Config struct {
EnableV2Multicast bool
DNS bool
DefaultSubnet string
ProcPath string // path to reach host /proc filesystem
}

type Plugin struct {
Expand Down Expand Up @@ -62,15 +63,15 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
endChan := make(chan error, 1)

if plugin.Socket != "" {
globalListener, err := listenAndServe(dockerClient, weave, plugin.Socket, endChan, "global", false, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast)
globalListener, err := listenAndServe(dockerClient, weave, plugin.Socket, endChan, "global", false, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast, plugin.ProcPath)
if err != nil {
return err
}
defer os.Remove(plugin.Socket)
defer globalListener.Close()
}
if plugin.MeshSocket != "" {
meshListener, err := listenAndServe(dockerClient, weave, plugin.MeshSocket, endChan, "local", true, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast)
meshListener, err := listenAndServe(dockerClient, weave, plugin.MeshSocket, endChan, "local", true, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast, plugin.ProcPath)
if err != nil {
return err
}
Expand All @@ -87,15 +88,15 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
return <-endChan
}

func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam, dns bool, isPluginV2, forceMulticast bool) (net.Listener, error) {
func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam, dns bool, isPluginV2, forceMulticast bool, procPath string) (net.Listener, error) {
var name string
if isPluginV2 {
name = pluginV2Name
} else {
name = pluginNameFromAddress(address)
}

d, err := netplugin.New(dockerClient, weave, name, scope, dns, isPluginV2, forceMulticast)
d, err := netplugin.New(dockerClient, weave, name, scope, dns, isPluginV2, forceMulticast, procPath)
if err != nil {
return nil, err
}
Expand Down
1 change: 1 addition & 0 deletions prog/weaver/main.go
Expand Up @@ -453,6 +453,7 @@ func main() {

pluginConfig.DNS = !noDNS
pluginConfig.DefaultSubnet = defaultSubnet.String()
pluginConfig.ProcPath = procPath
plugin := plugin.NewPlugin(pluginConfig)

// The weave script always waits for a status call to succeed,
Expand Down

0 comments on commit 15f21f1

Please sign in to comment.