
nftables नियमों के परीक्षण के लिए एक नियतात्मक नेटवर्क सैंडबॉक्स। यह फ़ायरवॉल लॉजिक को सुरक्षित रूप से सत्यापित करने के लिए अल्पकालिक Linux नेटवर्क नेमस्पेस (netns) और Scapy का उपयोग करता है।
NSE क्यों? • विशेषताएँ • आवश्यकताएँ • स्थापना • त्वरित शुरुआत • यह कैसे काम करता है • परियोजना संरचना
लाइव Linux सिस्टम पर फ़ायरवॉल नियमसेट का परीक्षण करना महत्वपूर्ण जोखिम पैदा करता है: विकृत नियम SSH प्रबंधन सत्रों को गिरा सकते हैं, परीक्षण के दौरान स्पष्ट ट्रैफ़िक लीक कर सकते हैं, या होस्ट पर अनाथ फ़ायरवॉल टेबल सक्रिय छोड़ सकते हैं।
Network Sandbox Engine (NSE) एक सुरक्षित, पुनरुत्पादनीय परीक्षण हार्नेस प्रदान करता है। यह अल्पकालिक Linux नेटवर्क नेमस्पेस का निर्माण करता है, वर्चुअल ईथरनेट जोड़े को जोड़ता है, nftables नियमसेट संकलित करता है, और Scapy का उपयोग करके कृत्रिम लेयर 2 और लेयर 3 पैकेट इंजेक्ट करता है। सभी मूल्यांकन सैंडबॉक्स नेमस्पेस के भीतर होता है: होस्ट फ़ायरवॉल स्थिति कभी नहीं बदली जाती।
प्रमुख वास्तुशिल्प गुण:
nse_<uuid>) में लोड किए जाते हैं और टियरडाउन के दौरान पूरी तरह से हटा दिए जाते हैं।nse/ 98% परीक्षण कवरेज पर ~1150 कथन है।NSE नेटवर्क नेमस्पेस बनाता है, nftables नियमसेट लोड करता है और कर्नेल ट्रेस इवेंट पढ़ता है, इसलिए यह रूट के रूप में चलता है। यह किसी भी प्रकार का सॉकेट, पोर्ट या RPC एंडपॉइंट नहीं खोलता — यह एक लाइब्रेरी और एक CLI है जिसे आप आमंत्रित करते हैं, और यह केवल एक रन की अवधि के लिए विशेषाधिकार रखता है।
संस्करण 2.1.0 ने FastAPI/Svelte वेब इंटरफ़ेस को हटा दिया जो पहले के रिलीज़ में
शामिल था। वह इंटरफ़ेस 2.0.0 से आगे रूट के रूप में इन-प्रोसेस चलता था, जो एक
परीक्षण उपकरण के लिए एक बड़ी हमला सतह थी; यदि आपको इसकी आवश्यकता हो तो कोड
टैग v2.0.0 पर git इतिहास में बना हुआ है।
फ़ायरवॉल परीक्षण एक नकारात्मक दावा है — "यह पैकेट पार नहीं हुआ" — और एक नकारात्मक दावा तब तक कुछ नहीं है जब तक कि उपकरण के काम करने के बारे में ज्ञात न हो। एक ट्रेस मॉनिटर जो कभी कर्नेल से जुड़ा ही नहीं और एक फ़ायरवॉल जिसने सब कुछ अवरुद्ध कर दिया, बाइट-समान आउटपुट उत्पन्न करते हैं।
इसलिए NSE ऐसा निर्णय रिपोर्ट करने से इनकार करता है जिसे वह मापा हुआ नहीं दिखा सकता:
कैनरी पैकेट को ट्रेस आईडी द्वारा परिणामों से बाहर रखा जाता है, इसलिए वे आपकी निर्णय स्ट्रीम में कभी नहीं दिखाई देते।
सूट साबित करता है कि यह कायम है, बजाय इसका दावा करने के: make test-blind पार्सर
को कुछ भी समझने के लिए मजबूर करता है, और बिल्ड तब तक विफल होता है जब तक रनर
गैर-शून्य से बाहर नहीं निकलता। वह जॉब हर पुश पर CI में चलता है।
run_test_pipeline) जो संरचित Pydantic मॉडल (TestRequest, TraceEvent) लौटाता है।nse_<id>) सीधे होस्ट से जुड़ा हुआ।nse_router_<id>) और सर्वर (nse_server_<id>) श्रृंखला।nse-runner) के लिए घोषणात्मक YAML टेस्ट सूट निष्पादित करें। गलत निर्णय पर और उस निर्णय पर भी गैर-शून्य से बाहर निकलता है जिसे देखने में वह विफल रहा।mypy --strict), वास्तुशिल्प सीमा प्रवर्तन (import-linter), ruff फ़ॉर्मेटिंग, और एक कवरेज रैचेट (, न्यूनतम 98%)।nft)ip)ip netns और कर्नेल ट्रेस संचालन के लिए आवश्यक)Debian या Ubuntu सिस्टम पर:
sudo apt update && sudo apt install -y nftables iproute2 conntrack
CLI समर्थन के साथ कोर इंजन स्थापित करें:
pip install "network-sandbox-engine[cli]"
स्थानीय विकास के लिए:
git clone https://github.com/onyks-os/NetworkSandboxEngine.git
cd NetworkSandboxEngine
make setup
import asyncio
from nse.core.netns_controller import NetnsController
from nse.core.pipeline import run_test_pipeline
from nse.models.test_request import TestRequest, PacketSpec
rules = """
table ip filter {
chain input {
type filter hook input priority 0; policy drop;
tcp dport 80 accept
}
}
"""
request = TestRequest(
rules=rules,
packets=[
PacketSpec(protocol="tcp", src_ip="10.0.0.1", dst_ip="10.0.0.2", dst_port=80),
PacketSpec(protocol="tcp", src_ip="10.0.0.1", dst_ip="10.0.0.2", dst_port=22),
],
)
async def main():
controller = NetnsController()
events = await run_test_pipeline(request=request, controller=controller)
for evt in events:
if evt.verdict:
print(f"[{evt.chain}] Verdict: {evt.verdict}")
asyncio.run(main())
एक टेस्ट फ़ाइल firewall_test.yaml बनाएँ:
tests:
- name: "Allow HTTP Port 80, Drop SSH Port 22"
topology: simple
rules: |
table ip filter {
chain input {
type filter hook input priority 0; policy drop;
tcp dport 80 accept
}
}
packets:
- protocol: tcp
src_ip: 10.0.0.1
dst_ip: 10.0.0.2
dst_port: 80
expected_verdict: ACCEPT
- protocol: tcp
src_ip: 10.0.0.1
dst_ip: 10.0.0.2
dst_port: 22
expected_verdict: DROP
expected_verdict प्रति पैकेट है। अज्ञात कुंजियाँ डिफ़ॉल्ट होने के बजाय
अस्वीकार कर दी जाती हैं, इसलिए एक टाइपो सूट को विफल कर देता है बजाय चुपचाप
एक ऐसी अपेक्षा बनने के जो आपने कभी नहीं लिखी।
रूट विशेषाधिकारों के साथ सूट चलाएँ:
sudo nse-runner --file firewall_test.yaml
एक्ज़िट कोड: 0 सभी पैकेट मेल खाए; 1 एक निर्णय गलत था या इंजन
एक निर्णय देख नहीं सका। ओरेकल त्रुटियाँ फ़ायरवॉल विफलताओं से अलग रिपोर्ट की जाती हैं,
क्योंकि उनका अर्थ है कि माप टूट गया, नियमसेट नहीं।
podman build -t nse .
podman run --rm --cap-add=NET_ADMIN --cap-add=NET_RAW \
-v "$PWD/firewall_test.yaml:/suite.yaml:ro" nse --file /suite.yaml
आपके नियमों का परीक्षण जिस nftables संस्करण के विरुद्ध किया जाता है उसे पिन करने के लिए उपयोगी।
NSE एक संरचित बहु-चरणीय निष्पादन पाइपलाइन के माध्यम से Linux कर्नेल नेटवर्क सबसिस्टम और ट्रेस इंटरफ़ेस को ऑर्केस्ट्रेट करता है:
graph TD
subgraph Step1["1. Test Specification"]
Req["<b>TestRequest</b><br/>ruleset + packets + topology"]
end
subgraph Step2["2. Ephemeral Netns Sandbox"]
direction TB
Netns["<b>Netns Setup</b><br/>nse_<id> & veth links"]
RuleEng["<b>Rule Engine</b><br/>validate & load nftables"]
Inject["<b>Scapy Injector</b><br/>L2/L3 packet injection"]
NFT["<b>Kernel nftables</b><br/>meta nftrace set 1"]
Netns --> RuleEng
RuleEng --> Inject
Inject --> NFT
end
subgraph Step3["3. Trace Evaluation & Oracle"]
direction TB
Harvester["<b>Trace Harvester</b><br/>nft monitor trace stream"]
Oracle["<b>Deterministic Oracle</b><br/>TraceEvents & verdicts"]
Harvester --> Oracle
end
Step1 --> Step2
Step2 --> Step3RuleEngine.validate() nft --check -f का उपयोग करके नियमसेट का ड्राई-रन करता है।NetnsController पृथक नेटवर्क नेमस्पेस बनाता है और वर्चुअल ईथरनेट (veth) इंटरफ़ेस कॉन्फ़िगर करता है।meta nftrace set 1) के साथ लोड किए जाते हैं।ScapyInjector veth लिंक पर कृत्रिम फ़्रेम इंजेक्ट करता है।TraceHarvester nft monitor trace इवेंट कैप्चर करता है और संरचित TraceEvent ऑब्जेक्ट लौटाता है।पूर्ण तकनीकी विशिष्टताओं के लिए, देखें तकनीकी वास्तुकला गाइड।
NetworkSandboxEngine/
├── nse/ # Core PyPI package (network-sandbox-engine)
│ ├── core/ # Kernel primitives, pipeline, and naming rules
│ ├── models/ # Pydantic models (TestRequest, PacketSpec, TraceEvent)
│ └── cli/ # Headless YAML runner entrypoint
├── docs/ # Architecture specs and MkDocs web documentation
├── tests/ # Unit, golden file, and privileged e2e tests
│ └── fixtures/nft_trace/ # Golden `nft monitor trace` corpus
├── pyproject.toml # Build backend configuration
└── Makefile # Local automation and CI workflow
एक टैग। git push origin vX.Y.Z बिल्ड करता है, Sigstore के साथ हस्ताक्षर करता है,
GitHub Release प्रकाशित करता है, TestPyPI पर अपलोड करता है, TestPyPI से इंस्टॉल करता है
और इसका स्मोक-टेस्ट करता है, और उसके बाद ही PyPI पर अपलोड करता है। make release-dry
के साथ पूर्वाभ्यास करें।
देखें docs/RELEASING.md।
पूर्ण इंटरैक्टिव वेब दस्तावेज़ीकरण यहाँ उपलब्ध है:
https://onyks-os.github.io/nse/
स्थानीय रूप से दस्तावेज़ीकरण बनाएँ:
make docs
http://127.0.0.1:8000 पर हॉट-रीलोड के साथ दस्तावेज़ीकरण सर्व करें:
make docs-serve
स्थिर लिंटिंग और यूनिट परीक्षण चलाएँ:
make verify
पूर्ण स्थानीय CI सत्यापन चलाएँ (लिंटिंग, यूनिट परीक्षण, फ्रंटएंड बिल्ड, डॉक्स बिल्ड, PyPI स्मोक टेस्ट, और विशेषाधिकार प्राप्त एकीकरण परीक्षण शामिल हैं):
make ci-local
यह परियोजना MIT लाइसेंस के अंतर्गत लाइसेंस प्राप्त है।
| गारंटी | तंत्र |
|---|
| मॉनिटर पहले परीक्षण पैकेट से पहले जुड़ा था | एक तैयारी कैनरी इंजेक्ट की जाती है और तब तक पुनः इंजेक्ट की जाती है जब तक उसका कर्नेल ट्रेस नहीं देखा जाता। कोई अवलोकन नहीं, कोई रन नहीं। |
| मॉनिटर अंतिम के बाद अभी भी जुड़ा था | इंजेक्शन के बाद एक जीवंतता कैनरी चलती है। यदि यह छूट जाती है, तो निर्णय स्ट्रीम को काटा हुआ घोषित किया जाता है। |
| पार्सर समझ गया कि कर्नेल ने क्या कहा | जिन ट्रेस पंक्तियों से कोई पैटर्न मेल नहीं खाता, उन्हें गिना जाता है, और शून्य से ऊपर कोई भी गिनती डिबग लॉग के बजाय एक त्रुटि है। |
| मॉनिटर चुपचाप नहीं मरा | रीड लूप रिकॉर्ड करता है कि यह क्यों समाप्त हुआ — साफ़ स्टॉप, अप्रत्याशित EOF, टाइमआउट या क्रैश — और केवल साफ़ स्टॉप स्वीकार्य है। |
| अनुपस्थित निर्णय पास नहीं है | CLI रनर तब विफल होता है जब देखे गए निर्णयों की संख्या अपेक्षित संख्या से भिन्न हो, किसी भी दिशा में। |
make test-cov