Change:
What happened: is set by in both iptables and ipvs mode. This causes a security issue; A host on the local segment can actually route 127.0.0.1 to a k8s-node and access ports that really should be local. Linux doc; What you expected to happen: Make configurable and set only when needed. How to reproduce it (as minimally and precisely as possible): On a machine on the same network segment as the k8s nodes; The example uses port which is opened by kubelet on 127.0.0.1 only; I really can't the the connect working myself on plain linux with the instruction above. I got this info from others who claim they can. What I do see though is that the syn-ack is sent back, so I guess some spy program can exploit this; If you set manually on the target node the syn-acks will not be sent back; Anything else we need to know?: Related issue Environment: Kubernetes version (use ): Cloud provider or hardware configuration: Kvms on Ubuntu OS (e.g: ): Kernel (e.g. ): Install tools: "from scratch" Network plugin and version (if this is a network-related bug): (any) Others:
/sig network
/triage unresolved Comment when the issue is assessed and confirmed. I am a bot run by vllry. ‍
Are there any reasons to set in the ipvs proxier? If not, I will make a PR to remove it. Considering the problems described in I don't think it makes any difference.
To set set the enabler for proxy-mode=iptables;
/cc
Hi all, Just to add a confirmatory post on this. I've just run up an experiment which looks like this single node Kubeadm 1.18.2 cluster with Weave as CNI, running on Ubuntu 18.04.3 server in VMWare Workstation on Linux. Straight install no changes from the standard process. Server IP is 192.168.41.208client is ubuntu 18.04.3 in VMWare workstation on Linux. Client IP is 192.168.41.248 On the client I ran (as per the original post) The listening ports on the server are Listening ports on the client are From the client run Response received : - So looks like it's possible to get app. level traffic back, over the local LAN. Obviously if there's any services that are assuming some level of security based on listening on localhost only, this may not apply.
I don't have the full context for this but in doing some digging I think this was mostly because iptables had it. I wouldn't be surprised though if disabling it broke some functionality that users depend on. For IPVS, even though we don't permit node port via localhost (yet), it sounds like it still has implications for when the source is from localhost?
This allows some corner cases of in iptables, but honestly I forget the details. I'm baffled why the kernel would respond to localhost traffic when it's clearly martian.
This seems relevant background:
Well - thats what the documentation says it does.. :) "Do not consider loopback addresses as martian source or destination" (from: ) Here are some further explanation and suggestions as to secure use of this (by other people) - that seems useful
I believe is enabled so that pods with HostPort set and services of type NodePort are truly equivalent to host ports. That is to say, I should be able to connect to not know that it's actually handled by a pod. I seem to recall this being lifted directly from libnetwork, but memory is extremely hazy.
Also, none of this works for ipv6; there is no equivalent, as addresses cannot escape their zone.
Yes, that is reported in;
If this issue has been triaged, please comment . If you aren't able to handle this issue, consider unassigning yourself and/or adding the label. I am a bot run by vllry. ‍
The case is connecting to . Let's say that's 8888, pointing to pod 10.0.0.1:9999. packet. PREROUTING rules run, do DNAT, add conntrack entry. packet is decision. normally, 127.0.0.1 would be dropped as a martian, but permits this. The outgoing interface is decided. POSTROUTING rules run, do MASQ, add conntrack entry. packet is now This sets up the conntrack entries for the packet to flow back from the pod to the tcp socket on localhost. You need to get the packet past the martian barrier, though, for this to work.
Can people use 0.0.0.0:NODEPORT ? Activating an insecure sysctls and trying to secure it seems wrong.
BTW does 127.0.0.1:$NODEPORT work with IPVS ? It's not working on my CentOS7 Calico cluster
No it doesn't work with ipvs, please see;
0 doesn't work (it's also local). wondering if we can make it work with ip rule / ip route but without route_localnet
Since accessing localhost:nodeport from the host never worked in IPVS mode (see 's comment), how do you feel about not setting the sysctl (or even setting it to 0)? It will make easy for users to patch their clusters if they run kube-proxy as a daemonset (we plan to do that)
+1 from me as long as we test it and ensure it doesn't break any existing behavior. There were previous feature requests to actually allow localhost:nodeport but given the security implications it sounds like we should avoid it.
I want to re-open this because I want to discuss the "real" fix. Clearly we have disagreement between ipvs and iptables about whether node-ports should work on localhost. I know of at least one use-case for it and I know that, at some point in the past, people were relying on it. But IPVS doesn't support it at all. Does anyone know about out-of-tree implementations? What do they support? I am anxious about shutting this off for iptables, since users MIGHT be relying on it. It's actually kind of "obvious" that it should work. That it DOESN'T is surprising (though apparently not fatally so). Are there any smaller mitigations we can take?
If this issue has been triaged, please comment . If you aren't able to handle this issue, consider unassigning yourself and/or adding the label. I am a bot run by vllry. ‍
localhost:nodeport works with Cilium but I am unsure how much load-balancing cilium handles (I deployed the "standard" yaml with ipv6 enabled); Update; localhost:nodeport does not work with Cilium and proxy-mode=ipvs so it seems Cilium only acts as cni-plugin by default. I am pretty sure does not support localhost:nodeport since it uses and should have the same limitation as in ipvs-mode.
K3s relies on for their forwarding of the endpoint via "ssh", please see But if they want to support ipv6 that does not work so...
Deployed with "all-features" yaml and kube-proxy disabled. Access to localhost:nodeport does not work users who disable do not suffer from the security issue
Cilium's BPF-based kube-proxy replacement supports accessing a NodePort service via , and thanks to BPF it does NOT set (therefore, it's not vulnerable to CVE-2020-8558). See You probably ran on an old kernel version which does not support some features required by the BPF NodePort. You can check to see what the kube-proxy replacement features were enabled.
Issues go stale after 90d of inactivity. Mark the issue as fresh with . Stale issues rot after an additional 30d of inactivity and eventually close. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle stale
Stale issues rot after 30d of inactivity. Mark the issue as fresh with . Rotten issues close after an additional 30d of inactivity. If this issue is safe to close now please do so with . Send feedback to sig-testing, kubernetes/test-infra and/or . /lifecycle rotten
Issues go stale after 90d of inactivity. Mark the issue as fresh with . Stale issues rot after an additional 30d of inactivity and eventually close. If this issue is safe to close now please do so with . Send feedback to sig-contributor-experience at . /lifecycle stale
I'm going to close it since kubelet a rule to mitigate the problem for kube-proxy iptables and IPVS totally disable it /close reopen if you feel that something is missing
Closing this issue. <detailsIn response to : I'm going to close it since kubelet a rule to mitigate the problem for kube-proxy iptables and IPVS totally disable it /close reopen if you feel that something is missing Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details

Discussion:
klog.Errorf("Failed to ensure rule to drop packet marked by %v in %v chain %v: %v", KubeMarkDropChain, utiliptables.TableFilter, KubeFirewallChain, err) return } <ins> // drop all non-local packets to localhost if they're not part of an existing // forwarded connection. See #90259 if !kl.iptClient.IsIPv6() { // ipv6 doesn't have this issue if _, err := kl.iptClient.EnsureRule(utiliptables.Append, utiliptables.TableFilter, KubeFirewallChain, "-m", "comment", "--comment", "block incoming localnet connections", "--dst", "127.0.0.0/8", "!", "--src", "127.0.0.0/8", "-m", "conntrack", "!", "--ctstate", "RELATED,ESTABLISHED,DNAT", "-j", "DROP"); err != nil { klog.Errorf("Failed to ensure rule to drop invalid localhost packets in %v chain %v: %v", utiliptables.TableFilter, KubeFirewallChain, err) return } } </ins> if _, err := kl.iptClient.EnsureRule(utiliptables.Prepend, utiliptables.TableFilter, utiliptables.ChainOutput, "-j", string(KubeFirewallChain)); err != nil { klog.Errorf("Failed to ensure that %s chain %s jumps to %s: %v", utiliptables.TableFilter, utiliptables.ChainOutput, KubeFirewallChain, err) return