PageSourceSearch

https://archive-os-3-28.netlify.app/assets/js/cbee503e.5a811b82.js

js archive-os-3-28.netlify.app collected 2026-10-03 11:34:24 UTC 11,474 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunktigera_docs=self.webpackChunktigera_docs||[]).push([["2894"],{65829:function(e,n,o){o.r(n),o.d(n,{frontMatter:()=>i,toc:()=>l,default:()=>h,metadata:()=>t,assets:()=>c,contentTitle:()=>a});var t=JSON.parse('{"id":"network-policy/hosts/protect-hosts-tutorial","title":"Protect hosts tutorial","description":"Learn how to secure incoming traffic from outside the cluster using Calico host endpoints with network policy, including allowing controlled access to specific Kubernetes services.","source":"@site/calico_versioned_docs/version-3.28/network-policy/hosts/protect-hosts-tutorial.mdx","sourceDirName":"network-policy/hosts","slug":"/network-policy/hosts/protect-hosts-tutorial","permalink":"/calico/3.28/network-policy/hosts/protect-hosts-tutorial","draft":false,"unlisted":false,"editUrl":"https://github.com/tigera/docs/edit/main/calico_versioned_docs/version-3.28/network-policy/hosts/protect-hosts-tutorial.mdx","tags":[],"version":"3.28","frontMatter":{"description":"Learn how to secure incoming traffic from outside the cluster using Calico host endpoints with network policy, including allowing controlled access to specific Kubernetes services."},"sidebar":"calicoSidebar","previous":{"title":"Protect Kubernetes nodes","permalink":"/calico/3.28/network-policy/hosts/kubernetes-nodes"},"next":{"title":"Apply policy to forwarded traffic","permalink":"/calico/3.28/network-policy/hosts/host-forwarded-traffic"}}'),s=o(37937),r=o(17869);let i={description:"Learn how to secure incoming traffic from outside the cluster using Calico host endpoints with network policy, including allowing controlled access to specific Kubernetes services."},a="Protect hosts tutorial",c={},l=[];function d(e){let n={a:"a",admonition:"admonition",br:"br",code:"code",em:"em",h1:"h1",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"protect-hosts-tutorial",children:"Protect hosts tutorial"})}),"\n",(0,s.jsx)(n.p,{children:"Imagine that the administrator of a Kubernetes cluster wants to secure it as much as\npossible against incoming traffic from outside the cluster. But suppose that\nthe cluster provides various useful services that are exposed as Kubernetes\nNodePorts, i.e., as well-known TCP port numbers that appear to be available on\nany node in the cluster. The administrator does want to expose some\nof those NodePorts to traffic from outside."}),"\n",(0,s.jsx)(n.p,{children:"In this example we will use pre-DNAT policy applied to the external interfaces\nof each cluster node:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"to disallow incoming traffic from outside, in general"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"but then to allow incoming traffic to particular NodePorts."}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"We use pre-DNAT policy for these purposes, instead of normal host endpoint\npolicy, because:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"We want the protection against general external traffic to apply regardless\nof where that traffic is destined for - for example, to a locally hosted\npod, or to a pod on another node, or to a local server process running on\nthe host itself. Pre-DNAT policy is enforced in all of those cases - as we\nwant - whereas normal host endpoint policy is not enforced for traffic going\nto a local pod."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["We want to write this policy in terms of the advertised NodePorts, not in\nterms of whatever internal port numbers those may be transformed to.\nkube-proxy on the ingress node will use a DNAT to change a NodePort number\nand IP address to those of one of the pods that backs the relevant Service.\nOur policy therefore needs to take effect ",(0,s.jsx)(n.em,{children:"before"})," that DNAT - and that\nmeans that it must be a pre-DNAT policy."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.admonition,{type:"note",children:(0,s.jsxs)(n.p,{children:["Note: This tutorial is intended to be used with 
1named host endpoints, i.e. host endpoints with ",(0,s.jsx)(n.code,{children:"interfaceName"})," set to a specific interface name.\nThis tutorial does not work, as-is, with host endpoints with ",(0,s.jsx)(n.code,{children:'interfaceName: "*"'}),"."]})}),"\n",(0,s.jsx)(n.p,{children:"Here is the pre-DNAT policy that we need to disallow incoming external traffic\nin general:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"calicoctl apply -f - <<EOF\napiVersion: projectcalico.org/v3\nkind: GlobalNetworkPolicy\nmetadata:\n  name: allow-cluster-internal-ingress\nspec:\n  order: 10\n  preDNAT: true\n  applyOnForward: true\n  ingress:\n    - action: Allow\n      source:\n        nets: [10.240.0.0/16, 192.168.0.0/16]\n  selector: has(host-endpoint)\n---\napiVersion: projectcalico.org/v3\nkind: GlobalNetworkPolicy\nmetadata:\n  name: drop-other-ingress\nspec:\n  order: 20\n  preDNAT: true\n  applyOnForward: true\n  ingress:\n    - action: Deny\n  selector: has(host-endpoint)\nEOF\n"})}),"\n",(0,s.jsx)(n.p,{children:"Specifically, this policy allows traffic coming from IP addresses that are\nknown to be cluster-internal, and denies traffic from any other sources. For\nthe cluster-internal IP addresses in this example, we assume 10.240.0.0/16 for\nthe nodes' own IP addresses, and 192.168.0.0/16 for IP addresses that\nKubernetes will assign to pods; obviously you should adjust for the CIDRs that\nare in use in your own cluster."}),"\n",(0,s.jsx)(n.admonition,{type:"note",children:(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"drop-other-ingress"})," policy has a higher ",(0,s.jsx)(n.code,{children:"order"})," value than\n",(0,s.jsx)(n.code,{children:"allow-cluster-internal-ingress"}),", so that it applies ",(0,s.jsx)(n.em,{children:"after"}),"\n",(0,s.jsx)(n.code,{children:"allow-cluster-internal-ingress"}),".\nThe explicit ",(0,s.jsx)(n.code,{children:"drop-other-ingress"})," policy is needed because there is no\nautomatic default-drop semantic for pre-DNAT policy. There ",(0,s.jsx)(n.em,{children:"is"})," a\ndefault-drop semantic for normal host endpoint policy but\u2014as noted above\u2014normal\nhost endpoint policy is not always enforced."]})}),"\n",(0,s.jsxs)(n.p,{children:["We also need policy to allow ",(0,s.jsx)(n.em,{children:"egress"})," traffic through each node's external\ninterface. Otherwise, when we define host endpoints for those interfaces, no\negress traffic will be allowed from local processes (except for traffic that is\nallowed by the ",(0,s.jsx)(n.a,{href:"/calico/3.28/reference/host-endpoints/failsafe",children:"failsafe rules"}),". Because there is no default-deny\nrule for forwarded traffic, forwarded traffic will be allowed for host endpoints."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"calicoctl apply -f - <<EOF\napiVersion: projectcalico.org/v3\nkind: GlobalNetworkPolicy\nmetadata:\n  name: allow-outbound-external\nspec:\n  order: 10\n  egress:\n    - action: Allow\n  selector: has(host-endpoint)\nEOF\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"note",children:(0,s.jsxs)(n.p,{children:["These egress rules are defined as normal host endpoint policies, not\npre-DNAT, because pre-DNAT policy does not support egress rules. (Which is\nbecause pre-DNAT policies are enforced at a point in the Linux networking\nstack where it is not yet determined what a packet's outgoing interface will\nbe.)\nBecause these are normal host endpoint policies which do not\napply to forwarded traffic (",(0,s.jsx)(n.code,{children:"applyOnForward"})," is ",(0,s.jsx)(n.code,{children:"false"}),"), they\nare not enforced for traffic that is sent from a local pod.\nThe policy above allows applications or server processes running on the nodes\nthemselves (as opposed to in pods) to connect outbound to any destination.\nIn case you have a use case for restricting to particular IP addresses, you\ncan achieve that by adding a corresponding ",(0,s.jsx)(n.code,{children:"destination"})," spec."]})}),"\n",(0,s.jsxs)(n.p,{children:["Now we can define a host endpoint for the outwards-facing interface of each\nnode. The policies above all have a selector that makes them applicable to any\nendpoint with a ",(0,s.jsx)(n.code,{children:"host-endpoint"})," label, so we should include that label in our\ndefinitions. For example, for ",(0,s.jsx)(n.code,{children:"eth0"})," on ",(0,s.jsx)(n.code,{children:"node1"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"calicoctl apply -f - <<EOF\napiVersion: projectcalico.org/v3\nkind: HostEndpoint\nmetadata:\n  name: node1-eth0\n  labels:\n    host-endpoint: ingress\nspec:\n  interfaceName: eth0\n  node: node1\nEOF\n"})}),"\n",(0,s.jsxs)(n.p,{children:["After defining host endpoints for each node, you should find that internal\ncluster communications are all still working as normal\u2014for example, that you\ncan successfully execute commands like ",(0,s.jsx)(n.code,{children:"calicoctl get hep"})," and ",(0,s.jsx)(n.code,{children:"calicoctl get pol"}),"\u2014but that it is impossible to connect into the cluster from outside\n(except for any ",(0,s.jsx)(n.a,{href:"/calico/3.28/reference/host-endpoints/failsafe",children:"failsafe rules"}),".",(0,s.jsx)(n.br,{}),"\n","For example, if the\ncluster includes a Kubernetes Service that is exposed as NodePort 31852, you\nshould find, at this point, that that NodePort works from within the cluster,\nbut not from outside."]}),"\n",(0,s.jsx)(n.p,{children:"To open a pinhole for that NodePort, for external access, you can configure a\npre-DNAT policy like this:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"calicoctl apply -f - <<EOF\napiVersion: projectcalico.org/v3\nkind: GlobalNetworkPolicy\nmetadata:\n  name: allow-nodeport\nspec:\n  preDNAT: true\n  applyOnForward: true\n  order: 10\n  ingress:\n    - action: Allow\n      protocol: TCP\n      destination:\n        selector: has(host-endpoint)\n        ports: [31852]\n  selector: has(host-endpoint)\nEOF\n"})}),"\n",(0,s.jsxs)(n.p,{children:["If you wanted to make that NodePort accessible only through particular nodes, you could achieve that by giving those nodes a particular ",(0,s.jsx)(n.code,{children:"host-endpoint"})," label:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"host-endpoint: <special-value>\n"})}),"\n",(0,s.jsxs)(n.p,{children:["and then using ",(0,s.jsx)(n.code,{children:"host-endpoint=='<special-value>'"})," as the selector of the\n",(0,s.jsx)(n.code,{children:"allow-nodeport"})," policy, instead of ",(0,s.jsx)(n.code,{children:"has(host-endpoint)"}),"."]})]})}function h(e={}){let{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},17869:function(e,n,o){o.d(n,{R:()=>i,x:()=>a});var t=o(82645);let s={},r=t.createContext(s);function i(e){let n=t.useContext(r);return t.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.