पहले, मुझे पता है कि यह एक पुराना सवाल है लेकिन ...
मैं दशकों से अपने स्वयं के आधिकारिक, गैर पुनरावर्ती, DNS सर्वर चला रहा हूं, लेकिन कभी भी किसी भी DNS आधारित DDoS हमलों में शिकार नहीं हुआ - अब तक, जब मैं एक नए आईएसपी पर स्विच किया गया था। हजारों स्पूफ़ किए गए DNS प्रश्नों ने मेरे लॉग्स को भर दिया और मैं वास्तव में नाराज हो गया - मेरे सर्वर पर प्रभाव के बारे में इतना नहीं, बल्कि इस तथ्य ने मेरे लॉग्स और दुर्व्यवहार किए जाने की असहज भावना को दूर कर दिया। ऐसा लगता है कि हमलावर मेरे DNS का उपयोग " आधिकारिक नाम सर्वर हमले " में करने की कोशिश करता है ।
तो मुझे लगा कि, भले ही मैं अपने आंतरिक नेटवर्क के लिए पुनरावर्ती प्रश्नों को सीमित करता हूं (अन्य सभी को नकारते हुए), मैं बजाय सीपीयू में स्ट्रिंग सीपीयू पर खर्च करता हूं, जो कि खराब आईपी पते को नकारात्मक प्रतिक्रियाएं भेजने से कम है (मेरे लॉग में कम अव्यवस्था, कम) नेटवर्क ट्रैफ़िक और मेरी खुद की एक उच्च संतुष्टि स्तर)।
मैंने ऐसा करना शुरू कर दिया जैसा कि बाकी सभी लोग करते हैं , यह पता करें कि किस डोमेन नाम को क्वेर किया गया है और एक लक्षित DROP के साथ उस डोमेन पर एक स्ट्रिंग मैच बनाया है। लेकिन मुझे जल्द ही एहसास हुआ कि मैं बड़ी मात्रा में नियमों का पालन करूंगा, उनमें से प्रत्येक सीपीयू चक्र का उपभोग करेगा। इसलिए क्या करना है? चूंकि मैं एक पुनरावर्ती नाम सर्वर नहीं चलाता हूं, इसलिए मुझे लगा कि मैं उन वास्तविक क्षेत्रों पर मिलान कर सकता हूं, जिनके लिए मैं आधिकारिक हूं और बाकी सभी चीजों को छोड़ दूंगा।
Iptables में मेरी डिफ़ॉल्ट नीति ACCEPT है, यदि आपकी नीति DROP है, तो शायद आपको कुछ समायोजन करने की आवश्यकता है यदि आप निम्नलिखित समाधान का उपयोग करना चाहते हैं।
मैं अपना ज़ोन कॉन्फ़िगरेशन एक अलग फ़ाइल (/etc/bind/onym.conf.local) में रखता हूं, आइए इसे एक उदाहरण के लिए उपयोग करें:
zone "1.168.192.in-addr.arpa" { // Private
type master;
allow-query { 192.168.1.0/24; 127.0.0.1; };
allow-transfer { 127.0.0.1; };
file "/etc/bind/db.192.168.1";
};
zone "home.example.net" { // Private
type master;
allow-query { 192.168.1.0/24; 127.0.0.1; };
allow-transfer { 127.0.0.1; };
file "/etc/bind/pri/db.home.example.net";
};
zone "example.net" {
type master;
file "/etc/bind/pri/db.example.net";
allow-transfer { 127.0.0.1; 8.8.8.8; };
};
zone "example.com" {
type slave;
masters { 8.8.8.8; };
file "sec.example.com";
allow-transfer { 127.0.0.1; };
notify no;
};
zone "subdomain.of.example.nu" {
type slave;
masters { 8.8.8.8; };
file "sec.subdomain.of.example.nu";
allow-transfer { 127.0.0.1; };
notify no;
};
मेरे पहले दो ज़ोन पर "// प्राइवेट" टिप्पणी पर ध्यान दें, मैं इसका उपयोग निम्न स्क्रिप्ट में मान्य ज़ोन की सूची से बाहर करने के लिए करता हूं।
#!/usr/bin/perl
# zone2iptables - Richard Lithvall, april 2014
#
# Since we want to match not only example.net, but also (for example)
# www.example.net we need to set a reasonable maximum value for a domain
# name in our zones - 100 character should be more that enough for most people
# and 255 is the absolute maximum allowed in rfc1034.
# Set it to 0 (zero) if you would like the script to fetch each zone (axfr)
# to get the actual max value.
$maxLengthOfQueryName=255;
$externalInterface="eth1";
print "# first time you run this, you will get error on the 3 first commands.\n";
print "# It's here to make it safe/possible to periodically run this script.\n";
print "/sbin/iptables -D INPUT -i $externalInterface -p udp --dport 53 -j DNSvalidate\n";
print "/sbin/iptables -F DNSvalidate\n";
print "/sbin/iptables -X DNSvalidate\n";
print "#\n";
print "# now, create the chain (again)\n";
print "/sbin/iptables -N DNSvalidate\n";
print "# and populate it with your zones\n";
while(<>){
if(/^zone\s+"(.+)"\s+\{$/){
$zone=$1;
if($maxLengthOfQueryName){
$max=$maxLengthOfQueryName;
} else {
open(DIG,"dig -t axfr +nocmd +nostats $zone |");
$max=0;
while(<DIG>){
if(/^(.+?)\.\s/){
$max=(length($1)>$max)?length($1):$max;
}
}
close(DIG);
}
printf("iptables -A DNSvalidate -m string --from 40 --to %d --hex-string \"",($max+42));
foreach $subdomain (split('\.',$zone)){
printf("|%02X|%s",length($subdomain),$subdomain);
}
print("|00|\" --algo bm -j RETURN -m comment --comment \"$zone\"\n");
}
}
print "# and end the new chain with a drop\n";
print "/sbin/iptables -A DNSvalidate -j DROP\n";
print "# And, at last, make the new chain active (on UDP/53)\n";
print "/sbin/iptables -A INPUT -i $externalInterface -p udp --dport 53 -j DNSvalidate\n";
ज़ोन कॉन्फ़िगरेशन फ़ाइल के साथ उपरोक्त स्क्रिप्ट को तर्क के रूप में चलाएं।
root:~/tmp/# ./zone2iptables.pl /etc/bind/named.conf.local
# first time you run this, you will get error on the 3 first commands.
# It's here to make it safe/possible to periodically run this script.
/sbin/iptables -D INPUT -i eth1 -p udp --dport 53 -j DNSvalidate
/sbin/iptables -F DNSvalidate
/sbin/iptables -X DNSvalidate
#
# now, create the chain (again)
/sbin/iptables -N DNSvalidate
# and populate it with your zones
iptables -A DNSvalidate -m string --from 40 --to 297 --hex-string "|07|example|03|net|00|" --algo bm -j RETURN -m comment --comment "example.net"
iptables -A DNSvalidate -m string --from 40 --to 297 --hex-string "|07|example|03|com|00|" --algo bm -j RETURN -m comment --comment "example.com"
iptables -A DNSvalidate -m string --from 40 --to 297 --hex-string "|09|subdomain|02|of|07|example|02|nu|00|" --algo bm -j RETURN -m comment --comment "subdomain.of.example.nu"
# and end the new chain with a drop
/sbin/iptables -A DNSvalidate -j DROP
# And, at last, make the new chain active (on UDP/53)
/sbin/iptables -A INPUT -i eth1 -p udp --dport 53 -j DNSvalidate
एक स्क्रिप्ट में आउटपुट को सेव करें, इसे एक शेल या पाइप में कॉपी करें और नई चेन बनाने के लिए अपने टर्मिनल में पेस्ट करें और सभी अमान्य डेटा प्रश्नों को फ़िल्टर करें।
नई श्रृंखला में प्रत्येक नियम पर पैकेट (और बाइट) काउंटर को देखने के लिए रन / sbin / iptables -L DNSvalidate -nvx (आप इसे और अधिक कुशल बनाने के लिए सूची के शीर्ष पर अधिकांश पैकेट वाले ज़ोन को स्थानांतरित करना चाह सकते हैं)।
उम्मीद है कि किसी को यह उपयोगी मिल सकता है :)