मेरा सोचा हुआ सबसे शक्तिशाली FreeBSD पैकेट फ़िल्टर (pf.conf)

13 min

language: ja bn en es hi pt ru zh-cn zh-tw

नमस्ते, मैं मुनो हूँ।

इस बार, मैं अपने हालिया पैकेट फ़िल्टर कॉन्फ़िगरेशन को पेश करना चाहता हूँ जिसके साथ मैं छेड़छाड़ कर रहा हूँ।

वर्तमान सेटिंग्स

यह कुछ इस प्रकार है।
पैकेट फ़िल्टर (Packet Filter) के मामले में:
NAT, rdr जैसे रूपांतरण नियम पहले मैच होने वाले पर लागू होते हैं।
pass, block जैसे फ़िल्टर नियम अंतिम मैच होने वाले पर लागू होते हैं।
यह इसकी कार्यप्रणाली है।

इस स्थिति में, पठनीयता के लिए, मैंने सभी फ़िल्टर नियमों को quick पर सेट किया है ताकि उस समय मैच होने वाला नियम तुरंत लागू हो जाए।
हालाँकि, fail2ban के block नियमों के लिए जिन्हें मैं व्यापक रूप से लॉग करना चाहता हूँ, मैंने उन्हें अंत में रखा है ताकि बिना किसी चूक के लॉगिंग सुनिश्चित हो सके।
जहाँ संभव हो, मैं उन चीज़ों के लिए टिप्पणियाँ छोड़ दूँगा।

set skip on lo
set block-policy drop
set optimization conservative
set state-policy if-bound
set ruleset-optimization basic
wanint="vtnet0"
# WireGuard Configuration
wg_ifs  = "{ wg0, wg1 }"
wg_net = "10.1.0.0/24"
wg_ports="{51820}"
table <wg_clients> const { 10.1.0.2, 10.1.0.4, 10.1.0.22 }
#### -- Scrub Rules -- ####
scrub in on $wanint all random-id max-mss 1360
scrub out on $wanint all random-id max-mss 1360
scrub in all
scrub out all
#### -- NAT Rules -- ####
# WireGuard Clients NAT
nat on $wanint inet from <wg_clients> to any -> ($wanint)
block all
#### -- Fail2Ban Rules -- ####
anchor "f2b/*"
pass out quick keep state
#### -- UDP Rules -- ####
pass in quick on $wg_ifs from $wg_net to any keep state
pass in quick on $wanint proto udp from any to ($wanint) port $wg_ports keep state
# HTTP/3 Protocol
pass in quick on $wanint proto udp to ($wanint) port 443 keep state
#### -- TCP Rules -- ####
# Mail Protocols
pass in quick proto tcp from any to ($wanint) port {25, 465, 993, 995} synproxy state
# HTTP
pass in quick on $wanint proto tcp to ($wanint) port {80, 443} modulate state

set block-policy drop

नियमों से मेल न खाने वाले सभी पैकेटों को drop कर दिया जाता है।
return के मामले में, TCP के लिए यह RST वापस भेजकर दूसरे पक्ष को सूचित करता है और कनेक्शन बंद कर देता है।
UDP के मामले में, चूंकि कोई TCP कनेक्शन नहीं होता है, यह केवल ICMP port unreachable वापस करता है।

set optimization conservative

दस्तावेजों के अनुसार, यह एक रूढ़िवादी (conservative) अनुकूलन सेटिंग है।
aggressive के मामले में, कनेक्शन को प्राथमिकता के आधार पर समाप्त कर दिया जाता है, लेकिन WireGuard जैसे वातावरण में जहाँ आप निरंतर कनेक्शन बनाए रखना चाहते हैं, कनेक्शन केवल इसलिए काट दिया जाएगा क्योंकि कोई नया पैकेट नहीं आया है।

इसके अलावा, satellite जैसा विकल्प भी है, जो काफी दिलचस्प लगता है।

       high-latency
             A high-latency environment (such  as  a  satellite  connec-
             tion).
       satellite
             Alias for high-latency.

set state-policy if-bound

यह state को बनाए रखकर और उसे याद रखकर पैकेटों को पारित करके विसंगतियों को रोकता है।
pfctl -ss का परिणाम state है, और उदाहरण के लिए, निम्नलिखित कॉन्फ़िगरेशन में:

क्लाइंट ←→ wg ←→ सर्वर

चूंकि state इस जानकारी से जुड़ा होता है कि 'इसे किस इंटरफ़ेस पर बनाया गया था', केवल उसी इंटरफ़ेस के माध्यम से होने वाले संचार को मान्य करके विसंगतियों को रोका जाता है।

सामान्य floating के मामले में:
प्रवेश: wg0
निकास: vtnet0
वापसी: vtnet0 या wg0 दोनों ठीक हैं

हालाँकि, state-policy if-bound के मामले में:
प्रवेश: wg0
निकास: vtnet0
वापसी: अनिवार्य रूप से wg0 होनी चाहिए, अन्यथा यह विफल हो जाएगा

set ruleset-optimization basic

यह नियमों के अनुकूलन को समझदारी से संभालता है।
आधिकारिक दस्तावेजों से:

  1. डुप्लिकेट नियमों को हटाना

  2. उन नियमों को हटाना जो किसी अन्य नियम का हिस्सा हैं

  3. लाभकारी होने पर कई नियमों को एक टेबल में संयोजित करना

  4. मूल्यांकन प्रदर्शन को बेहतर बनाने के लिए नियमों को पुनर्व्यवस्थित करना

हिंदी में:

  1. डुप्लिकेट नियमों को हटाना

  2. उन नियमों को हटाना जो किसी अन्य नियम में शामिल हैं

  3. आवश्यकतानुसार कई नियमों को एक टेबल में संयोजित करना

  4. मूल्यांकन प्रदर्शन को बेहतर बनाने के लिए नियमों के क्रम को बदलना

इसका मतलब है कि भले ही आप pf नियमों को लापरवाही से लिखें, यह उन्हें सफाई से व्यवस्थित कर देगा। इसे सक्षम करने मात्र से, आप अपनी सुविधा के अनुसार पठनीय pf नियम लिख सकते हैं और यह उन्हें समझदारी से व्यवस्थित कर देगा—एक शानदार सुविधा।

वेरिएबल परिभाषा

WAN इंटरफ़ेस नाम निर्दिष्ट करना

wanint="vtnet0"

निर्धारित IPv4 पते और एक स्पष्ट निकास IP के रूप में परिभाषित

exsrv1 = "163.44.113.145"

WireGuard पर वेरिएबल और टेबल की परिभाषा

wg_ifs  = "{ wg0, wg1 }"
wg_net = "10.1.0.0/24"
wg_ports="{51820}"
table <wg_clients> const { 10.1.0.2, 10.1.0.4, 10.1.0.22 }

Scrub Rules

इस मामले में, WAN से आने वाले और बाहर जाने वाले दोनों पैकेटों के लिए MSS मान निर्दिष्ट किया गया है।
"all random-id के बारे में ऐसा लगता है कि यह OS को पैकेट से पहचाने जाने से रोकने के लिए है, लेकिन जहाँ तक मैंने GNU/Linux पर sudo tcpdump -n -v -i $interface के साथ जाँच की है, यह डिफ़ॉल्ट रूप से सक्षम लगता है।

04:15:18.538048 IP (tos 0x0, ttl 52, id 61686, offset 0, flags [DF], proto TCP (6), length 52)
04:15:18.538049 IP (tos 0x0, ttl 52, id 61687, offset 0, flags [DF], proto TCP (6), length 131)
04:15:18.538179 IP (tos 0x0, ttl 64, id 65430, offset 0, flags [DF], proto TCP (6), length 52)
04:15:18.538223 IP (tos 0x0, ttl 52, id 61688, offset 0, flags [DF], proto TCP (6), length 131)

इसके अलावा, WAN इंटरफ़ेस के अलावा अन्य इंटरफ़ेस को भी scrub करने के लिए in all और out all भी सेट किया गया है।

scrub in on $wanint all random-id max-mss 1360
scrub out on $wanint all random-id max-mss 1360
scrub in all
scrub out all

NAT Rules

विशिष्ट WireGuard क्लाइंट साइड WireGuard सर्वर साइड के WAN इंटरफ़ेस के NAT के माध्यम से बाहर निकलते हैं।
हालाँकि, इस मामले में यह केवल IPv4 के माध्यम से बाहर निकलता है। ऐसा इसलिए है क्योंकि WireGuard सर्वर साइड पर IPv6 एड्रेस वितरित नहीं किए जा रहे हैं, इसलिए केवल inet from का उपयोग किया गया है।

nat on $wanint inet from <wg_clients> to any -> ($wanint)

Fail2Ban Rules

Fail2Ban के साथ हमलावर के IP को pf टेबल में जोड़ने और उसे ब्लॉक करने का नियम। इसे अंत में रखकर, जो पैकेट किसी भी नियम से मेल नहीं खाते, उन्हें anchor "f2b/*" के माध्यम से pf टेबल में जोड़े गए IP से आने वाले पैकेटों को Fail2Ban नियमों में भेजा जाता है।
इसे ऊपर रखा गया है क्योंकि इसे quick वाले फ़िल्टर नियमों से पहले मैच होना आवश्यक है।
इसके ठीक पहले डिफ़ॉल्ट नियम block all है, इसलिए जो पैकेट यहाँ मैच नहीं होते वे सभी block कर दिए जाएँगे।

/usr/local/etc/fail2ban/action.d/pf.conf:

# Option: block
#
# The action you want pf to take.
# Probably, you want "block quick", but adjust as needed.
# If you want to log all blocked use "blog log quick"
block = block quick

इस सेटिंग से block quick का Fail2ban नियम जुड़ जाता है, इसलिए इसे ऊपर रखा गया है।

यानी, सबसे पहले anchor "f2b/*" के माध्यम से pf टेबल में जोड़े गए IP के पैकेटों को Fail2Ban नियमों में भेजा जाता है, और फिर

anchor "f2b/*"

फ़िल्टर नियम के रूप में, सबसे पहले बाहर जाने वाले पैकेटों को अनुमति देने वाला नियम रखा गया है।

pass out quick keep state

UDP Rules

WireGuard सर्वर के लिए अनुमति नियम।
51820/udp को अनुमति दें और $wg_ifs पर सभी WireGuard वर्चुअल NIC को अनुमति दें।
शायद किसी अनहोनी की स्थिति के लिए इसे और अधिक सख्त बनाया जाना चाहिए?

pass in quick on $wg_ifs from $wg_net to any keep state
pass in quick on $wanint proto udp from any to ($wanint) port $wg_ports keep state

इस मामले में, चूँकि state पहले से ही बनी हुई है, इसलिए WireGuard टनल के माध्यम से आने वाले सभी पैकेटों को अनुमति दी जाएगी। यदि यह क्रम उल्टा होता, तो pass in quick on $wg_ifs from $wg_net to any keep state नियम काम नहीं करता क्योंकि यह WireGuard टनल होने के आधार पर है।

HTTP/3 को सक्षम करने के लिए 443/udp को अनुमति दें

# HTTP/3 Protocol
pass in quick on $wanint proto udp to ($wanint) port 443 keep state

TCP Rules

जैसा कि nmap आदि का उपयोग करने वाले लोग जानते होंगे, TCP के मामले में पोर्ट स्कैनिंग बहुत तेज़ी से की जाती है, इसलिए केवल पोर्ट बदलने से हमलावर इसे जल्दी ढूंढ लेंगे। UDP पोर्ट के मामले में nmap स्कैन में बहुत समय लगता है, इसलिए इसे अधिक सुरक्षित बनाने के लिए SSH एक्सेस केवल WireGuard टनल के माध्यम से ही संभव बनाया गया है। संक्षेप में, मुझे लगता है कि सबसे सुरक्षित कॉन्फ़िगरेशन वह है जहाँ TCP को प्रभावी रूप से UDP में लपेटा गया हो।
Fail2ban लागू है, इसलिए SSH हमले की स्थिति में हमलावर के IP को pf टेबल में जोड़कर ब्लॉक कर दिया जाता है। यह वास्तव में एक हनीपॉट की तरह है।

मेल प्रोटोकॉल के लिए, synproxy सक्षम करके SYN Flood हमलों को रोकने का प्रयास किया गया है।
इस मामले में HTTP के लिए ($wanint) के साथ गंतव्य IP निर्दिष्ट करने का कारण WAN इंटरफ़ेस को दिए गए IP एड्रेस के साथ गतिशील रूप से मैच करना है। स्पष्ट रूप से inet निर्दिष्ट नहीं करने का कारण IPv4 और IPv6 दोनों को अनुमति देना है।

IPv6 के माध्यम से आने वाले पैकेटों के लिए, चूँकि गंतव्य IP ($wanint) के साथ निर्दिष्ट है, यह WAN इंटरफ़ेस को दिए गए IPv6 एड्रेस के साथ गतिशील रूप से मैच होगा।

# Mail Protocols
pass in quick proto tcp from any to ($wanint) port {25, 465, 993, 995} synproxy state
# HTTP
pass in quick on $wanint proto tcp to ($wanint) port {80, 443} modulate state

बस इतना ही, यह काफी लंबा हो गया...

Related Posts