Compare commits

...
16 Commits
Author SHA1 Message Date
Bryan Boreham f78c4dacc5 Add release v2.6.3 2020-05-28 10:12:54 +00:00
Bryan Boreham 9245b73913 Merge pull request #3805 from weaveworks/block-remote-localhost
Block non-local traffic to the Weave control port
2020-05-28 10:50:55 +01:00
Bryan Boreham 6ee961b068 Block non-local traffic to the Weave control port
We expect the loopback address 127.0.0.1 to be accessible only from
the local host.

We need to allow RELATED,ESTABLISHED traffic which may be the return
path of a Kubernetes HostPort.
2020-05-27 16:43:50 +00:00
Bryan Boreham 1f920513de Merge pull request #3804 from weaveworks/npc-errors-metrics2
metric for NPC errors
2020-05-23 20:43:55 +01:00
Bryan Boreham 15f21f1899 Merge pull request #3801 from weaveworks/disable-accept-ra
Disable accept_ra on Weave Net interfaces
2020-05-22 11:00:50 +01:00
Bryan Boreham 09a204b978 NPC: increment metric each time an error is logged 2020-05-22 09:55:07 +00:00
Murali Reddy 77fbb2c12b introduce weavenpc_policy_enforcement_errors prometheus metric
to track number of errors occured during enforcing network policies

Fixes #3791
2020-05-22 09:54:11 +00:00
Bryan Boreham 6ad3e69faf Plumb through /proc path config to Docker plugin 2020-05-18 14:47:26 +00:00
Bryan Boreham e2088ef401 Disable accept_ra setting on interfaces we create 2020-05-14 10:21:41 +00:00
Bryan Boreham 0f3864968e refactor: supply /proc path to CreateAndAttachVeth()
Move the assumptions about where we're running up towards the caller.
2020-05-14 10:21:09 +00:00
Bryan Boreham 2f235daa1c Merge pull request #3777 from weaveworks/eks
add steps to install weave-net on EKS
2020-04-02 12:32:21 +01:00
Murali Reddy 438a5f5fd1 clarify pods connect to api server 2020-04-02 16:12:02 +05:30
Bryan Boreham b051ef0878 Merge pull request #3790 from weaveworks/npc-errors
Weave-npc: while logging differentiate between fatal and non-fatal errors
2020-04-02 11:24:10 +01:00
Murali Reddy 48015aa7be Weave-npc: while logging differentiate between fatal and non-fatal errors 2020-04-02 15:08:15 +05:30
Murali Reddy 4e3acfdc02 add note on apiserver being on EKS managed network 2020-02-26 10:29:50 +05:30
Murali Reddy 11915948a2 add steps to install weave-net on EKS 2020-02-26 10:27:01 +05:30
13 changed files with 111 additions and 44 deletions

No files matched your search

+9
View File
@@ -1,3 +1,12 @@
## Release 2.6.3
This release has a couple of security improvements, and some other fixes.
* Block non-local traffic to the Weave control port #3805
* Tell Linux not to accept router advisory messages #3801
* Network Policy Controller: add a metric to show errors while operating #3804
* Network Policy Controller: don't treat named port as a fatal error #3790
## Release 2.6.2
This release fixes a regression found in 2.6.1 release and removes a possible case
+6
View File
@@ -54,6 +54,12 @@ func SetLogLevel(levelname string) {
Log.Level = level
}
func CheckError(e error) {
if e != nil {
Log.Error(e)
}
}
func CheckFatal(e error) {
if e != nil {
Log.Fatal(e)
+20 -11
View File
@@ -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
@@ -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{}
@@ -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
@@ -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")
@@ -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 := ""
@@ -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)
}
@@ -465,6 +469,11 @@ func configureIPTables(config *BridgeConfig, ips ipset.Interface) error {
}
}
// Block non-local traffic to the Weave control port
if err = ipt.AppendUnique("filter", "INPUT", "-p", "tcp", "--dst", "127.0.0.1", "-m", "addrtype", "!", "--src-type", "LOCAL", "-m", "conntrack", "!", "--ctstate", "RELATED,ESTABLISHED", "-j", "DROP"); err != nil {
return err
}
if config.NPC {
// Steer traffic via the NPC.
+3 -3
View File
@@ -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")
}
+17 -8
View File
@@ -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)
@@ -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)
@@ -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
@@ -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)
}
@@ -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
@@ -219,15 +229,14 @@ 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
@@ -235,7 +244,7 @@ func ConfigureARP(prefix, rootPath string) error {
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)
+9
View File
@@ -22,6 +22,12 @@ var (
},
[]string{"protocol", "dport"},
)
PolicyEnforcementErrors = prometheus.NewCounter(
prometheus.CounterOpts{
Name: "weavenpc_policy_enforcement_errors",
Help: "Errors occured in enforcing the network policies.",
},
)
)
func gatherMetrics() {
@@ -95,6 +101,9 @@ func Start(addr string) error {
if err := prometheus.Register(blockedConnections); err != nil {
return err
}
if err := prometheus.Register(PolicyEnforcementErrors); err != nil {
return err
}
http.Handle("/metrics", promhttp.Handler())
+4 -2
View File
@@ -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,
@@ -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
@@ -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)
}
+2 -7
View File
@@ -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)
}
+5 -4
View File
@@ -32,6 +32,7 @@ type Config struct {
EnableV2Multicast bool
DNS bool
DefaultSubnet string
ProcPath string // path to reach host /proc filesystem
}
type Plugin struct {
@@ -62,7 +63,7 @@ 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
}
@@ -70,7 +71,7 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
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
}
@@ -87,7 +88,7 @@ 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
@@ -95,7 +96,7 @@ func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address
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
}
+15 -8
View File
@@ -34,7 +34,14 @@ var (
bridgePortName string
)
func handleError(err error) { common.CheckFatal(err) }
func handleError(err error) {
if err != nil {
metrics.PolicyEnforcementErrors.Inc()
common.Log.Error(err)
}
}
func handleFatal(err error) { common.CheckFatal(err) }
func makeController(getter cache.Getter, resource string,
objType runtime.Object, handlers cache.ResourceEventHandlerFuncs) cache.Controller {
@@ -240,19 +247,19 @@ func root(cmd *cobra.Command, args []string) {
}
config, err := rest.InClusterConfig()
handleError(err)
handleFatal(err)
client, err := kubernetes.NewForConfig(config)
handleError(err)
handleFatal(err)
ipt, err := iptables.New()
handleError(err)
handleFatal(err)
ips := ipset.New(common.LogLogger(), maxList)
handleError(resetIPTables(ipt))
handleError(resetIPSets(ips))
handleError(createBaseRules(ipt, ips))
handleFatal(resetIPTables(ipt))
handleFatal(resetIPSets(ips))
handleFatal(createBaseRules(ipt, ips))
npc := npc.New(nodeName, ipt, ips, client)
@@ -339,5 +346,5 @@ func main() {
rootCmd.PersistentFlags().IntVar(&maxList, "max-list-size", 1024, "maximum size of ipset list (for namespaces)")
rootCmd.PersistentFlags().StringVar(&bridgePortName, "bridge-port-name", "vethwe-bridge", "name of the brige port on which packets are received and sent")
handleError(rootCmd.Execute())
handleFatal(rootCmd.Execute())
}
+1
View File
@@ -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,
+19 -1
View File
@@ -7,6 +7,8 @@ search_type: Documentation
The following topics are discussed:
* [Installation](#install)
* [Installing on GKE](#gke)
* [Installing on EKS](#eks)
* [Upgrading the Daemon Sets](#daemon-sets)
* [CPU and Memory Requirements](#resources)
* [Pod Eviction](#eviction)
@@ -71,10 +73,26 @@ Shut down Kubernetes, and _on all nodes_ perform the following:
Then relaunch Kubernetes and install the addon as described
above.
**Note:** Installing on GKE
### <a name="gke"></a> Installing on GKE
Please note that you must grant the user the ability to create roles in Kubernetes before launching Weave Net.
This is a prerequisite to use use role-based access control on GKE. Please see the GKE [instructions](https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control).
### <a name="gke"></a> Installing on EKS
EKS by default installs `amazon-vpc-cni-k8s` CNI. Please follow below steps to use Weave-net as CNI
- create EKS cluster in any of [prescribed](https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html) way
- delete `amazon-vpc-cni-k8s` deamonset by running `kubectl delete ds aws-node -n kube-system` command
- delete `/etc/cni/net.d/10-aws.conflist` on each of the node
- edit instance security group to allow TCP 6783 and UDP 6783/6784 ports
- flush iptables nat, mangle, filter tables to clear any iptables configurations done by `amazon-vpc-cni-k8s`
- restart kube-proxy pods to reconfigure iptables
- apply weave-net daemoset by following above installation steps
- delete existing pods so they get recreated in Weave pod CIDR's address-space.
Please note that while pods can connect to the Kubernetes API server for your cluser, API server will not be able to connect to the pods as API server nodes are not connected to Weave Net (they run on network managed by EKS).
### <a name="daemon-sets"></a> Upgrading the Daemon Sets
The DaemonSet definition specifies [Rolling
+1
View File
@@ -483,6 +483,7 @@ destroy_bridge() {
[ -n "$DOCKER_BRIDGE_IP" ] || DOCKER_BRIDGE_IP=$(util_op bridge-ip $DOCKER_BRIDGE)
run_iptables -t filter -D INPUT -d 127.0.0.1/32 -p tcp -m addrtype ! --src-type LOCAL -m conntrack ! --ctstate RELATED,ESTABLISHED -j DROP >/dev/null 2>&1 || true
run_iptables -t filter -D INPUT -i $DOCKER_BRIDGE -p udp --dport 53 -j ACCEPT >/dev/null 2>&1 || true
run_iptables -t filter -D INPUT -i $DOCKER_BRIDGE -p tcp --dport 53 -j ACCEPT >/dev/null 2>&1 || true