1"use strict";(self.webpackChunkkubearmor_io=self.webpackChunkkubearmor_io||[]).push([[7104],{5680:(e,t,n)=>{n.d(t,{xA:()=>c,yg:()=>y});var r=n(6540);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,a=function(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},g=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),u=p(n),g=a,y=u["".concat(s,".").concat(g)]||u[g]||d[g]||o;return n?r.createElement(y,l(l({ref:t},c),{},{components:n})):r.createElement(y,l({ref:t},c))}));function y(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,l=new Array(o);l[0]=g;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i[u]="string"==typeof e?e:a,l[1]=i;for(var p=2;p<o;p++)l[p]=n[p];return r.createElement.apply(null,l)}return r.createElement.apply(null,n)}g.displayName="MDXCreateElement"},8880:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>l,default:()=>d,frontMatter:()=>o,metadata:()=>i,toc:()=>p});var r=n(8168),a=(n(6540),n(5680));const o={slug:"kubearmor-network-segmentation-linux-vms",title:"Network Segmentation of Linux VMs using KubeArmor",authors:["atharvashah"],tags:["KubeArmor","Network Security","VM Security","Linux","Zero Trust","nftables","Cloud-Native Security"]},l="Network Segmentation of Linux VMs using KubeArmor",i={permalink:"/blog/kubearmor-network-segmentation-linux-vms",editUrl:"https://github.com/kubearmor/kubearmor.io/tree/main/blog/2026-04-14-KubeArmor-Network-Segmentation-Linux-VMs/index.md",source:"@site/blog/2026-04-14-KubeArmor-Network-Segmentation-Linux-VMs/index.md",title:"Network Segmentation of Linux VMs using KubeArmor",description:"alt text",date:"2026-04-14T00:00:00.000Z",formattedDate:"April 14, 2026",tags:[{label:"KubeArmor",permalink:"/blog/tags/kube-armor"},{label:"Network Security",permalink:"/blog/tags/network-security"},{label:"VM Security",permalink:"/blog/tags/vm-security"},{label:"Linux",permalink:"/blog/tags/linux"},{label:"Zero Trust",permalink:"/blog/tags/zero-trust"},{label:"nftables",permalink:"/blog/tags/nftables"},{label:"Cloud-Native Security",permalink:"/blog/tags/cloud-native-security"}],readingTime:8.85,hasTruncateMarker:!0,authors:[{name:"Atharva Shah",title:"DevRel @ KubeArmor | Accuknox",url:"https://github.com/highnessatharva",imageURL:"https://i.ibb.co/wh5qgYHG/remini-white-tee.jpg",key:"atharvashah"}],frontMatter:{slug:"kubearmor-network-segmentation-linux-vms",title:"Network Segmentation of Linux VMs using KubeArmor",authors:["atharvashah"],tags:["KubeArmor","Network Security","VM Security","Linux","Zero Trust","nftables","Cloud-Native Security"]},nextItem:{title:"Introducing USB Device Enforcement for Host Security",permalink:"/blog/kubearmor-usb-enforcement-host-security"}},s={authorsImageUrls:[void 0]},p=[{value:"The Gap That Hurt VM Security",id:"the-gap-that-hurt-vm-security",level:2},{value:"What Is the Network Policy Enforcer?",id:"what-is-the-network-policy-enforcer",level:2},{value:"Under the Hood: nftables",id:"under-the-hood-nftables",level:4},{value:"Default Posture and Enabling the Feature",id:"default-posture-and-enabling-the-feature",level:4},{value:"Policy Structure",id:"policy-structure",level:2},{value:"Example Policies",id:"example-policies",level:2}
1,{value:"Policy 1: Lock a VM to Its Private Network",id:"policy-1-lock-a-vm-to-its-private-network",level:4},{value:"Policy 2: Block Outbound DNS to External Resolvers",id:"policy-2-block-outbound-dns-to-external-resolvers",level:4},{value:"Policy 3: SSH Restricted to Jump Host (Progressive Enforcement)",id:"policy-3-ssh-restricted-to-jump-host-progressive-enforcement",level:4},{value:"Policy 4: Interface-Scoped Port Range for Backend Service Mesh",id:"policy-4-interface-scoped-port-range-for-backend-service-mesh",level:4},{value:"How It Fits Into a Zero Trust VM Architecture",id:"how-it-fits-into-a-zero-trust-vm-architecture",level:2},{value:"Getting Started",id:"getting-started",level:2},{value:"References",id:"references",level:2},{value:"Frequently Asked Questions",id:"frequently-asked-questions",level:2},{value:"Does KubeArmorNetworkPolicy replace KubeArmorHostPolicy?",id:"does-kubearmornetworkpolicy-replace-kubearmorhostpolicy",level:4},{value:"Does this work on distributions that still use iptables?",id:"does-this-work-on-distributions-that-still-use-iptables",level:4},{value:"Can I define both ingress and egress rules in a single policy?",id:"can-i-define-both-ingress-and-egress-rules-in-a-single-policy",level:4},{value:"What happens to traffic that does not match any policy?",id:"what-happens-to-traffic-that-does-not-match-any-policy",level:4},{value:"How is this different from a standard Linux firewall like ufw or firewalld?",id:"how-is-this-different-from-a-standard-linux-firewall-like-ufw-or-firewalld",level:4}],c={toc:p},u="wrapper";function d(e){let{components:t,...o}=e;return(0,a.yg)(u,(0,r.A)({},c,o,{components:t,mdxType:"MDXLayout"}),(0,a.yg)("p",null,(0,a.yg)("img",{alt:"alt text",src:n(4782).A,width:"4332",height:"2747"})),(0,a.yg)("p",null,"KubeArmor now enforces layer 3/4 network rules on Linux VMs via a new CRD: ",(0,a.yg)("inlineCode",{parentName:"p"},"KubeArmorNetworkPolicy"),". Policies support CIDR ranges, port ranges, interface scoping, and both ingress and egress control. Enforcement runs at the kernel via nftables and is stateful by default."),(0,a.yg)("h2",{id:"the-gap-that-hurt-vm-security"},"The Gap That Hurt VM Security"),(0,a.yg)("p",null,"KubeArmor already enforced process execution, file access, and protocol-level network syscalls on VMs. But layer 3 and layer 4 controls were missing. You could block a protocol, optionally filtered by process, but that was the ceiling."),(0,a.yg)("p",null,"You could not write: ",(0,a.yg)("em",{parentName:"p"},"accept TCP on port 5432 only from this CIDR, on this interface.")," No ingress/egress port control. No IP block rules. No port ranges. ",(0,a.yg)("inlineCode",{parentName:"p"},"KubeArmorNetworkPolicy")," closes that gap."),(0,a.yg)("p",null,"Network segmentation on Linux VMs has historically required either cloud security groups or a separately managed firewall tool. KubeArmor collapses both into a single policy plane that lives alongside your workload definitions."),(0,a.yg)("p",null,"In a segmented network, each VM zone (database tier, app tier, bastion) should only communicate with adjacent tiers on approved ports. Without kernel-level enforcement, those boundaries exist only on paper."),(0,a.yg)("h2",{id:"what-is-the-network-policy-enforcer"},"What Is the Network Policy Enforcer?"),(0,a.yg)("p",null,"A new feature that adds layer 3/4 network enforcement to KubeArmor for VMs. It introduces a dedicated CRD, ",(0,a.yg)("inlineCode",{parentName:"p"},"KubeArmorNetworkPolicy"),", separate from the three existing policy types."),(0,a.yg)("table",null,(0,a.yg)("thead",{parentName:"table"},(0,a.yg)("tr",{parentName:"thead"},(0,a.yg)("th",{parentName:"tr",align:null},(0,a.yg)("strong",{parentName:"th"},"CRD")),(0,a.yg)("th",{parentName:"tr",align:null},(0,a.yg)("strong",{parentName:"th"},"Target")),(0,a.yg)("th",{parentName:"tr",align:null},(0,a.yg)("strong",{parentName:"th"},"Enforcement Layer")),(0,a.yg)("th",{parentName:"tr",align:null},(0,a.yg)("strong",{parentName:"th"},"Use When")))),(0,a.yg)("tbody",{parentName:"table"},(0,a.yg)("tr",{parentName:"tbody"},(0,a.yg)("td",{parentName:"tr",align:null},(0,a.yg)("inlineCode",{parentName:"td"},"KubeArmorPolicy")),(0,a.yg)("td",{parentName:"tr",align:null},"Containers / pods"),(0,a.yg)("td",{parentName:"tr",align:null},"Process, file, syscall, protocol+process"),(0,a.yg)("td",{parentName:"tr",align:null},"Container workload hardening")),(0,a.yg)("tr",{parentName:"tbody"},(0,a.yg)("td",{parentName:"tr",align:null},(0,a.yg)("inlineCode",{parentName:"td"},"KubeArmorHostPolicy")),(0,a.yg)("td",{parentName:"tr",align:null},"VM / host"),(0,a.yg)("td",{parentName:"tr",align:null},"Process, file, syscall, protocol+process"),(0,a.yg)("td",{parentName:"tr",align:null},"Host-level process and file control")),(0,a.yg)("tr",{parentName:"tbody"},(0,a.yg)("td",{parentName:"tr",align:null},(0,a.yg)("inlineCode",{parentName:"td"},"KubeArmorNetworkPolicy")),(0,a.yg)("td",{parentName:"tr",align:null},"VM / host nodes, K8s Nodes"),(0,a.yg)("td",{parentName:"tr",align:null},"Layer 3/4: CIDR, port, port range, interface"),(0,a.yg)("td",{parentName:"tr",align:null},"IP-based and port-based VM network control")))),(0,a.yg)("p",null,(0,a.yg)("img",{parentName:"p",src:"https://accuknox.com/wp-content/uploads/kubearmor-vm-network-segmentation-1-1024x572.png",alt:"KubeArmor Policy CRD hierarchy and enforcement layers"})),(0,a.yg)("p",null,(0,a.yg)("em",{parentName:"p"},"Figure 1: KubeArmor policy CRD hierarchy and enforcement layers")),(0,a.yg)("h4",{id:"under-the-hood-nftables"},"Under the Hood: nftables"),(0,a.yg)("p",null,"KubeArmor translates ",(0,a.yg)("inlineCode",{parentName:"p"},"KubeArmorNetworkPolicy")," rules into nftables rules on the host. It creates its own table named ",(0,a.yg)("inlineCode",{parentName:"p"},"KubeArmor"),", with chains that hook into Linux's input and output hooks. Every applied policy becomes a rule inside those chains."),(0,a.yg)("p",null,"Two default rules are always present in every chain:"),(0,a.yg)("ul",null,(0,a.yg)("li",{parentName:"ul"},(0,a.yg)("strong",{parentName:"li"},"Loopback traffic is always allowed.")," Services communicating locally over ",(0,a.yg)("inlineCode",{parentName:"li"},"lo")," are not disrupted."),(0,a.yg)("li",{parentName:"ul"},(0,a.yg)("strong",{parentName:"li"},"Established and related connections are accepted"),", making the policy stateful. An ingress allow does not require a matching egress rule for reply packets.")),(0,a.yg)("blockquote",null,(0,a.yg)("p",{parentName:"blockquote"},"On startup, KubeArmor checks that nftables is present and running as root. If nftables is unavailable, the enforcer skips initialization. No silent failures.")),(0,a.yg)("h4",{id:"default-posture-and-enabling-the-feature"},"Default Posture and Enabling the Feature"),(0,a.yg)("table",null,(0,a.yg)("thead",{parentName:"table"},(0,a.yg)("tr",{parentName:"thead"},(0,a.yg)("th",{parentName:"tr",align:null},(0,a.yg)("strong",{parentName:"th"},"Setting")),(0,a.yg)("th",{parentName:"tr",align:null},(0,a.yg)("strong",{parentName:"th"},"Behavior")))),(0,a.yg)("tbody",{parentName:"table"},(0,a.yg)("tr",{parentName:"tbody"},(0,a.yg)("td",{parentName:"tr",align:null},"Default posture: Block"),(0,a.yg)("td",{parentName:"tr",align:null},"Traffic not matched by any policy is dropped.")),(0,a.yg)("tr",{parentName:"tbody"},(0,a.yg)("td",{parentName:"tr",align:null},"Default posture: Audit"),(0,a.yg)("td",{parentName:"tr",align:null},"Unmatched traffic is logged only. No blocking.")),(0,a.yg)("tr",{parentName:"tbody"},(0,a.yg)("td",{parentName:"tr",align:null},(0,a.yg)("inlineCode",{parentName:"td"}
1,"enableNetworkPolicyEnforcer: true")," (default)"),(0,a.yg)("td",{parentName:"tr",align:null},"Feature active. ",(0,a.yg)("inlineCode",{parentName:"td"},"KubeArmorNetworkPolicy")," resources are enforced.")),(0,a.yg)("tr",{parentName:"tbody"},(0,a.yg)("td",{parentName:"tr",align:null},(0,a.yg)("inlineCode",{parentName:"td"},"enableNetworkPolicyEnforcer: false")),(0,a.yg)("td",{parentName:"tr",align:null},"Feature disabled. Existing CRDs unaffected.")))),(0,a.yg)("h2",{id:"policy-structure"},"Policy Structure"),(0,a.yg)("p",null,"The spec mirrors Kubernetes ",(0,a.yg)("inlineCode",{parentName:"p"},"NetworkPolicy")," with two additions: an ",(0,a.yg)("inlineCode",{parentName:"p"},"action")," field and an ",(0,a.yg)("inlineCode",{parentName:"p"},"iface")," field. Anyone familiar with K8s network policies will read these without friction."),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-yaml"},"apiVersion: security.kubearmor.com/v1\nkind: KubeArmorNetworkPolicy\nmetadata:\n name: [policy name]\nspec:\n severity: [1-10] # optional (appears in alerts)\n tags: [\"tag\", ...] # optional (e.g., MITRE, STIG)\n message: [message] # optional (injected into alert logs)\n nodeSelector:\n matchLabels:\n [key]: [value] # target nodes by label\n ingress:\n - from:\n - ipBlock:\n cidr: [IP range] # IPv4 or IPv6\n iface: [if1, ...] # optional: scope to specific interfaces\n ports:\n - protocol: [TCP|UDP|SCTP]\n port: [number or name in string]\n endPort: [optional: defines a port range]\n egress: # mirrors ingress; uses 'to' instead of 'from'\n action: [Allow|Audit|Block]\n")),(0,a.yg)("table",null,(0,a.yg)("thead",{parentName:"table"},(0,a.yg)("tr",{parentName:"thead"},(0,a.yg)("th",{parentName:"tr",align:null},(0,a.yg)("strong",{parentName:"th"},"Field")),(0,a.yg)("th",{parentName:"tr",align:null},(0,a.yg)("strong",{parentName:"th"},"Required")),(0,a.yg)("th",{parentName:"tr",align:null},(0,a.yg)("strong",{parentName:"th"},"Notes")))),(0,a.yg)("tbody",{parentName:"table"},(0,a.yg)("tr",{parentName:"tbody"},(0,a.yg)("td",{parentName:"tr",align:null},(0,a.yg)("inlineCode",{parentName:"td"},"nodeSelector")),(0,a.yg)("td",{parentName:"tr",align:null},"Yes"),(0,a.yg)("td",{parentName:"tr",align:null},"Standard K8s label selector. System labels (",(0,a.yg)("inlineCode",{parentName:"td"},"kubernetes.io/hostname"),") also valid.")),(0,a.yg)("tr",{parentName:"tbody"},(0,a.yg)("td",{parentName:"tr",align:null},(0,a.yg)("inlineCode",{parentName:"td"},"ingress.from.ipBlock.cidr")),(0,a.yg)("td",{parentName:"tr",align:null},"No"),(0,a.yg)("td",{parentName:"tr",align:null},"Source IP range for inbound rules. IPv4 or IPv6.")),(0,a.yg)("tr",{parentName:"tbody"},(0,a.yg)("td",{parentName:"tr",align:null},(0,a.yg)("inlineCode",{parentName:"td"},"egress.to.ipBlock.cidr")),(0,a.yg)("td",{parentName:"tr",align:null},"No"),(0,a.yg)("td",{parentName:"tr",align:null},"Destination IP range for outbound rules.")),(0,a.yg)("tr",{parentName:"tbody"},(0,a.yg)("td",{parentName:"tr",align:null},(0,a.yg)("inlineCode",{parentName:"td"},"iface")),(0,a.yg)("td",{parentName:"tr",align:null},"No"),(0,a.yg)("td",{parentName:"tr",align:null},"Restricts rule to named interfaces. Ports/protocol apply only to listed interfaces.")),(0,a.yg)("tr",{parentName:"tbody"},(0,a.yg)("td",{parentName:"tr",align:null},(0,a.yg)("inlineCode",{parentName:"td"},"port")),(0,a.yg)("td",{parentName:"tr",align:null},"No"),(0,a.yg)("td",{parentName:"tr",align:null},"Single port by number or name (",(0,a.yg)("inlineCode",{parentName:"td"},"ssh"),", ",(0,a.yg)("inlineCode",{parentName:"td"},"dns"),", ",(0,a.yg)("inlineCode",{parentName:"td"},"http"),", ",(0,a.yg)("inlineCode",{parentName:"td"},"https"),").")),(0,a.yg)("tr",{parentName:"tbody"},(0,a.yg)("td",{parentName:"tr",align:null},(0,a.yg)("inlineCode",{parentName:"td"},"endPort")),(0,a.yg)("td",{parentName:"tr",align:null},"No"),(0,a.yg)("td",{parentName:"tr",align:null},"If set, defines a range from ",(0,a.yg)("inlineCode",{parentName:"td"},"port")," to ",(0,a.yg)("inlineCode",{parentName:"td"},"endPort"),".")),(0,a.yg)("tr",{parentName:"tbody"},(0,a.yg)("td",{parentName:"tr",align:null},(0,a.yg)("inlineCode",{parentName:"td"},"action")),(0,a.yg)("td",{parentName:"tr",align:null},"Yes"),(0,a.yg)("td",{parentName:"tr",align:null},(0,a.yg)("inlineCode",{parentName:"td"},"Allow"),", ",(0,a.yg)("inlineCode",{parentName:"td"},"Block"),", or ",(0,a.yg)("inlineCode",{parentName:"td"},"Audit"),".")))),(0,a.yg)("p",null,(0,a.yg)("img",{parentName:"p",src:"https://accuknox.com/wp-content/uploads/kubearmor-vm-network-segmentation-2-1024x572.png",alt:"KubeArmor Network Policy structure"})),(0,a.yg)("h2",{id:"example-policies"},"Example Policies"),(0,a.yg)("h4",{id:"policy-1-lock-a-vm-to-its-private-network"},"Policy 1: Lock a VM to Its Private Network"),(0,a.yg)("p",null,"A database VM in subnet ",(0,a.yg)("inlineCode",{parentName:"p"},"10.0.1.0/24")," should only accept TCP connections from that subnet on port 5432. All other inbound TCP is blocked."),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-yaml"},'apiVersion: security.kubearmor.com/v1\nkind: KubeArmorNetworkPolicy\nmetadata:\n name: allow-private-subnet-ingress\nspec:\n nodeSelector:\n matchLabels:\n role: database\n ingress:\n - from:\n - ipBlock:\n cidr: "10.0.1.0/24"\n ports:\n - protocol: TCP\n port: "5432"\n severity: 7\n action: Block\n')),(0,a.yg)("blockquote",null,(0,a.yg)("p",{parentName:"blockquote"},(0,a.yg)("strong",{parentName:"p"},"Attack vector blocked:")," Lateral movement to database nodes. A compromised host outside the subnet cannot reach port 5432 even if cloud security groups are misconfigured.")),(0,a.yg)("p",null,"This is the canonical micro-segmentation pattern: the database tier accepts connections only from the app tier CIDR, and nothing else. No firewall rule outside the VM can guarantee this if the cloud NSG drifts."),(0,a.yg)("h4",{id:"policy-2-block-outboun
1d-dns-to-external-resolvers"},"Policy 2: Block Outbound DNS to External Resolvers"),(0,a.yg)("p",null,"Block UDP port 53 traffic to ",(0,a.yg)("inlineCode",{parentName:"p"},"8.8.8.8"),". Forces name resolution through internal DNS and closes the DNS tunneling C2 channel."),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-yaml"},'apiVersion: security.kubearmor.com/v1\nkind: KubeArmorNetworkPolicy\nmetadata:\n name: block-external-dns\nspec:\n nodeSelector:\n matchLabels:\n kubernetes.io/hostname: "prod-worker-01"\n egress:\n - to:\n - ipBlock:\n cidr: "8.8.8.8/32"\n ports:\n - protocol: UDP\n port: "dns"\n severity: 5\n action: Block\n')),(0,a.yg)("blockquote",null,(0,a.yg)("p",{parentName:"blockquote"},(0,a.yg)("strong",{parentName:"p"},"Attack vector blocked:")," DNS exfiltration and C2 callbacks via public resolvers. Leaves internal DNS resolution untouched.")),(0,a.yg)("h4",{id:"policy-3-ssh-restricted-to-jump-host-progressive-enforcement"},"Policy 3: SSH Restricted to Jump Host (Progressive Enforcement)"),(0,a.yg)("p",null,"SSH access to production VMs should only originate from the corporate jump host subnet (",(0,a.yg)("inlineCode",{parentName:"p"},"192.168.10.0/28"),"). Use a two-policy pattern: audit broadly first to baseline, then block."),(0,a.yg)("p",null,(0,a.yg)("strong",{parentName:"p"},"Policy A \u2014 Audit all SSH globally:")),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-yaml"},'apiVersion: security.kubearmor.com/v1\nkind: KubeArmorNetworkPolicy\nmetadata:\n name: audit-ssh-all\nspec:\n nodeSelector:\n matchLabels:\n env: production\n ingress:\n - from:\n - ipBlock:\n cidr: "0.0.0.0/0"\n ports:\n - protocol: TCP\n port: "ssh"\n message: "SSH from outside jump host subnet detected"\n severity: 8\n action: Audit\n')),(0,a.yg)("p",null,"SSH access control is a segmentation boundary, not just an access policy. Restricting it by source CIDR enforces the separation between the management plane and the data plane at the host level."),(0,a.yg)("p",null,(0,a.yg)("strong",{parentName:"p"},"Policy B \u2014 Allow only the jump host subnet:")),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-yaml"},'apiVersion: security.kubearmor.com/v1\nkind: KubeArmorNetworkPolicy\nmetadata:\n name: allow-ssh-jumphost\nspec:\n nodeSelector:\n matchLabels:\n env: production\n ingress:\n - from:\n - ipBlock:\n cidr: "192.168.10.0/28"\n ports:\n - protocol: TCP\n port: "ssh"\n severity: 2\n action: Allow\n')),(0,a.yg)("blockquote",null,(0,a.yg)("p",{parentName:"blockquote"},"The ",(0,a.yg)("inlineCode",{parentName:"p"},"message")," field in Policy A surfaces directly in alert logs for SIEM ingestion. Run Audit for 48 hours, validate there are no false positives, then flip to Block.")),(0,a.yg)("h4",{id:"policy-4-interface-scoped-port-range-for-backend-service-mesh"},"Policy 4: Interface-Scoped Port Range for Backend Service Mesh"),(0,a.yg)("p",null,"A VM with two NICs: ",(0,a.yg)("inlineCode",{parentName:"p"},"eth0")," for external traffic, ",(0,a.yg)("inlineCode",{parentName:"p"},"eth1")," for internal service mesh. Restrict inbound traffic on ",(0,a.yg)("inlineCode",{parentName:"p"},"eth1")," to ports 8000\u20139000 from the internal CIDR only. ",(0,a.yg)("inlineCode",{parentName:"p"},"eth0")," is unaffected."),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-yaml"},'apiVersion: security.kubearmor.com/v1\nkind: KubeArmorNetworkPolicy\nmetadata:\n name: restrict-backend-mesh\nspec:\n nodeSelector:\n matchLabels:\n tier: backend\n ingress:\n - from:\n - ipBlock:\n cidr: "172.16.0.0/12"\n iface: ["eth1"]\n ports:\n - protocol: TCP\n port: "8000"\n endPort: 9000\n severity: 6\n action: Block\n')),(0,a.yg)("blockquote",null,(0,a.yg)("p",{parentName:"blockquote"},"Use ",(0,a.yg)("inlineCode",{parentName:"p"},"iface")," to prevent over-broad rules from affecting unrelated traffic paths. Common in hybrid cloud and service mesh deployments where VMs have separate NICs per traffic class.")),(0,a.yg)("h2",{id:"how-it-fits-into-a-zero-trust-vm-architecture"},"How It Fits Into a Zero Trust VM Architecture"),(0,a.yg)("p",null,(0,a.yg)("img",{parentName:"p",src:"https://accuknox.com/wp-content/uploads/kubearmor-vm-network-segmentation-3-1-1024x572.png",alt:"KubeArmor VM Network Segmentation - Zero Trust Architecture"})),(0,a.yg)("p",null,"Traditional network policies (cloud security groups, NSGs) operate at the cloud perimeter. They do not enforce on the VM itself. ",(0,a.yg)("inlineCode",{parentName:"p"},"KubeArmorNetworkPolicy")," enforces at the kernel via nftables, which means:"),(0,a.yg)("ul",null,(0,a.yg)("li",{parentName:"ul"},(0,a.yg)("strong",{parentName:"li"}
1,"Policy follows the workload"),", not the infrastructure boundary."),(0,a.yg)("li",{parentName:"ul"},(0,a.yg)("strong",{parentName:"li"},"Rules hold even if cloud-level security groups are misconfigured or bypassed.")),(0,a.yg)("li",{parentName:"ul"},(0,a.yg)("strong",{parentName:"li"},"Works in air-gapped, hybrid, or bare-metal deployments")," with no cloud networking controls.")),(0,a.yg)("p",null,"Combined with KubeArmor's process and file policies, you get defense-in-depth on every VM. A compromised process cannot make unauthorized outbound calls. An attacker who lands on the VM cannot reach internal services or external C2 if those paths are explicitly blocked."),(0,a.yg)("p",null,"Micro-segmentation means each VM enforces its own perimeter. KubeArmor achieves this without a separate network appliance or agent: the nftables rules live on the host itself and survive cloud perimeter changes."),(0,a.yg)("h2",{id:"getting-started"},"Getting Started"),(0,a.yg)("p",null,"The Network Policy Enforcer is enabled by default in recent KubeArmor releases."),(0,a.yg)("p",null,(0,a.yg)("strong",{parentName:"p"},"Verify the enforcer is active on your nodes:")),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-bash"},"kubectl get kubearmornodestatus \\\n -o jsonpath='{.items[*].status.networkPolicyEnforcer}'\n")),(0,a.yg)("p",null,(0,a.yg)("strong",{parentName:"p"},"Apply a policy:")),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-bash"},"kubectl apply -f nsp-allow-private-subnet-ingress.yaml\n")),(0,a.yg)("p",null,(0,a.yg)("strong",{parentName:"p"},"Inspect generated nftables rules on the host:")),(0,a.yg)("pre",null,(0,a.yg)("code",{parentName:"pre",className:"language-bash"},"sudo nft list table ip kubearmor\n")),(0,a.yg)("p",null,"Policy violations appear in KubeArmor alerts. Pipe the ",(0,a.yg)("inlineCode",{parentName:"p"},"message")," field into your SIEM for contextualized incident tickets."),(0,a.yg)("h2",{id:"references"},"References"),(0,a.yg)("ul",null,(0,a.yg)("li",{parentName:"ul"},(0,a.yg)("a",{parentName:"li",href:"https://docs.kubearmor.io/kubearmor/documentation/network_security_policy_specification"},"KubeArmor Network Policy Specification")),(0,a.yg)("li",{parentName:"ul"},(0,a.yg)("a",{parentName:"li",href:"https://docs.kubearmor.io/kubearmor/documentation/network_security_policy_examples"},"KubeArmor Network Policy Examples")),(0,a.yg)("li",{parentName:"ul"},(0,a.yg)("a",{parentName:"li",href:"https://github.com/kubearmor/KubeArmor/blob/main/getting-started/network_policy_enforcer.md"},"Network Policy Enforcer Guide")),(0,a.yg)("li",{parentName:"ul"},(0,a.yg)("a",{parentName:"li",href:"https://github.com/kubearmor/KubeArmor"},"KubeArmor GitHub"))),(0,a.yg)("h2",{id:"frequently-asked-questions"},"Frequently Asked Questions"),(0,a.yg)("h4",{id:"does-kubearmornetworkpolicy-replace-kubearmorhostpolicy"},"Does KubeArmorNetworkPolicy replace KubeArmorHostPolicy?"),(0,a.yg)("p",null,"No. They are complementary. ",(0,a.yg)("inlineCode",{parentName:"p"},"KubeArmorHostPolicy")," handles process execution, file access, and protocol-level syscall controls on the VM host. ",(0,a.yg)("inlineCode",{parentName:"p"},"KubeArmorNetworkPolicy")," handles CIDR, port, and interface rules at the network layer. Use both together for full depth."),(0,a.yg)("h4",{id:"does-this-work-on-distributions-that-still-use-iptables"},"Does this work on distributions that still use iptables?"),(0,a.yg)("p",null,"KubeArmor uses nftables, which ships by default on major Linux distributions (Ubuntu 20.04+, RHEL 8+, Debian 10+). On older distributions it is not pre-installed but can be manually installed on any system running Linux kernel 3.x+. On startup, KubeArmor checks for nftables availability. If nftables is present and KubeArmor is running as root, it initializes. iptables is not used by the Network Policy Enforcer."),(0,a.yg)("h4",{id:"can-i-define-both-ingress-and-egress-rules-in-a-single-policy"},"Can I define both ingress and egress rules in a single policy?"),(0,a.yg)("p",null,"Yes. A single ",(0,a.yg)("inlineCode",{parentName:"p"},"KubeArmorNetworkPolicy")," spec can contain both ",(0,a.yg)("inlineCode",{parentName:"p"},"ingress")," and ",(0,a.yg)("inlineCode",{parentName:"p"},"egress")," blocks. Define them independently with their own CIDR, interface, and port values."),(0,a.yg)("h4",{id:"what-happens-to-traffic-that-does-not-match-any-policy"},"What happens to traffic that does not match any policy?"),(0,a.yg)("p",null,"The behavior depends on your default network posture configuration. When running in allowlist mode (at least one allow-based policy is active), unmatched traffic follows the default posture \u2014 dropped if set to ",(0,a.yg)("inlineCode",{parentName:"p"},"Block"),", or logged and allowed through if set to ",(0,a.yg)("inlineCode",{parentName:"p"},"Audit"),". Outside of allowlist mode, unmatched traffic is recorded in host logs. Set your default posture explicitly before deploying ",(0,a.yg)("inlineCode",{parentName:"p"},"Block"),"-action policies to production."),(0,a.yg)("h4",{id:"how-is-this-different-from-a-standard-linux-firewall-like-ufw-or-firewalld"},"How is this different from a standard Linux firewall like ufw or firewalld?"),(0,a.yg)("p",null,"KubeArmor network policies implement micro-segmentation across a fleet of VMs declaratively, with the same GitOps workflow you already use for application policies. ",(0,a.yg)("inlineCode",{parentName:"p"},"ufw")," and ",(0,a.yg)("inlineCode",{parentName:"p"},"firewalld")," are standalone firewall managers with no policy-as-code workflow, no
1Kubernetes API surface, and no integration with workload identity or labels. ",(0,a.yg)("inlineCode",{parentName:"p"},"KubeArmorNetworkPolicy")," uses the same nftables kernel layer but is declared as a Kubernetes CRD, version-controlled, auditable, and scoped by node labels. It is also stateful by default and composable with process and file policies from the same agent."))}d.isMDXComponent=!0},4782:(e,t,n)=>{n.d(t,{A:()=>r});const r=n.p+"assets/images/image-0765825105421f0f3b5dcb871d6cb980.png"}}]);
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.