第11篇:Linux防火墻 黑名單管理

正常情況下,暴露于互聯(lián)網(wǎng)的服務(wù)器是不會收到來自目標(biāo)端口是137,138,139的數(shù)據(jù)包,若你對Samba協(xié)議熟悉的話,這三個端口是Windows系統(tǒng)用于請求NetBIOS主機名稱,若短短在10分鐘之內(nèi),你的服務(wù)器收到來自這些莫名奇妙的數(shù)據(jù)包,基本可以斷定是收到來自互聯(lián)網(wǎng)其他來歷不明源IP對你主機的端口掃描。

這些端口掃描,來源與Windows 2000/XP時代NetBIOS服務(wù)漏洞,包含netbios-ssn(139/tcp)以及netbios-ns(137/tcp),NetBios 會洩漏遠(yuǎn)程主機的ID以及的主機名稱,入侵者更可以使用密碼破解工具,對主機進行字典攻擊的,如下圖是筆者的Linux服務(wù)器在最近運行以來,收到來自這些惡意IP地址的端口掃描

如果你有閱讀我之前的Linux防火墻系列文章,應(yīng)該了解到如下firewalld的規(guī)則的重要性,我們來自可疑的數(shù)據(jù)包都做了日志記錄,但僅有日志記錄是遠(yuǎn)遠(yuǎn)不夠的,還要采取一些主動防御措施

這也是會有本篇隨筆的原因,所謂的主動防御就是Linux防火墻從目前的防火墻日志中提取那些惡意的IP地址,并制作一個黑名單寫入規(guī)則中,永久Ban掉這些惡意IP。

本篇會以防止端口掃描為例,這個案例中會用到這些direct規(guī)則

ipv4 mangle PORT_SCANNING 0 -m recent --name portscan --rcheck --seconds 25200 -j DROP
ipv4 mangle PORT_SCANNING 1 -m recent --name portscan --remove
ipv4 mangle PORT_SCANNING 2 -p tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix port_scan:
ipv4 mangle PORT_SCANNING 3 -p tcp --dport 139 -m recent --name portscan --set -j DROP
ipv4 mangle PORT_SCANNING 4 -p tcp --dport 138 -m recent --name portscan --set -j LOG --log-prefix port_scan:
ipv4 mangle PORT_SCANNING 5 -p tcp --dport 138 -m recent --name portscan --set -j DROP
ipv4 mangle PORT_SCANNING 6 -p tcp --dport 137 -m recent --name portscan --set -j LOG --log-prefix port_scan:
ipv4 mangle PORT_SCANNING 7 -p tcp --dport 137 -m recent --name portscan --set -j DROP

根據(jù)前面一篇的日志管理,我們將防火墻日志保存在/var/log/iptables.log這個文件中,也就是上文第一個插圖的日志記錄。我們需要從日志中提取有用的源IP地址。你應(yīng)該要想到“Python大法好,信Python得脫身??!

  • 下面的python程序就是從/var/log/iptables.log日志文件中提取每行記錄的跟源IP地址的關(guān)鍵字,
  • 并將這些源IP地址追加到一個集合中。
  • 最后將set集合中的ip地址逐行寫入一個叫ipList.txt的文本當(dāng)中

為什么要用set,而不用list呢?因為set數(shù)據(jù)接口可以除去重復(fù)的IP地址。這個Python程序沒什么好說的,一目了然。

#!/usr/bin/python3 
import os,re

logFile='/var/log/iptables.log'
blkIpFile='~/iplist.txt'

ip_pat=re.compile(r'SRC=(\d+\.\d+\.\d+\.\d+)')

if not os.path.exists(logFile):
    raise FileNotFoundError("{}文件不存在!!".format(logFile))

keyWords=["port_scan","syn_attack"]

res=None
blackIPs=set()

with open(logFile,'r') as f:
    data=f.readlines()
    
    for line in data:
        for word in keyWords:
            if word in line:
                res=ip_pat.findall(line)
                if len(res):
                    print("找到源ip:{}".format(res[1]))
                    blackIPs.add(res[1])
                break
            #if
        #end-for
    #end-for
#end-with


if not os.path.exists(blkIpFile):
    raise FileNotFoundError("{}文件不存在".format(blkIpFile))

with open(blkIpFile,'w') as f:
    
    if len(blackIPs)==0:
        raise ValueError("參數(shù)blackIPs為空!!\n")
    for item in blackIPs:
        f.write("{}\n".format(item))
    #end-for
#end-with

運行上面的腳本后,我們可以查看iplist.txt這個文本,筆者都驚呆了,運行短短十多天的服務(wù)器居然遭到650多個惡意IP地址


ss8.gif

接下來,需要用到firewalld的ipset選項,將上面的iplist.txt文件導(dǎo)入到firewalld的規(guī)則中,

ipset指定的IP地址集可以在防火墻區(qū)域中用作源地址過濾,也可以用作rich規(guī)則中的源地址。 在Red Hat Enterprise Linux 7中,首選方法是在direct規(guī)則中使用用firewalld創(chuàng)建的ipset。

以本文為例,創(chuàng)建一個名為“blk_src_ips”的ipset

firewall-cmd --permanent --new-ipset=blk_src_ips --type=hash:net

type選項中的hash:net對應(yīng)的是ipv4的網(wǎng)絡(luò)環(huán)境。 要創(chuàng)建用于IPv6的IP集,請?zhí)砑?-option = family = inet6選項。

接下來,就是使用--add-entries-from-file選項將iplist.txt的內(nèi)容導(dǎo)入到blk_src_ips的ipset空間中

irewall-cmd --permanent --ipset=blk_src_ips --add-entries-from-file=~/iplist.txt

跟著,我們在drop區(qū)域中定義一條源規(guī)則,將blk_src_ips的地址集作為源規(guī)則的源IP,我們之所以要使用drop區(qū)域是因為drop區(qū)域默認(rèn)就是任何綁定到該區(qū)域的IP地址或端口的數(shù)據(jù)包都一律丟棄。

firewall-cmd --permanent --zone=drop --add-source=ipset:blk_src_ips

最后一步,非常關(guān)鍵,一定要確保drop區(qū)域是防火墻最后要被執(zhí)行的默認(rèn)區(qū)域,因此一定要補上這條命令

firewall-cmd --permanent --set-default-zone=drop
firewall-cmd --reload

運行一段時間,或許你會發(fā)現(xiàn)的默認(rèn)區(qū)域的策略已經(jīng)生效了,PRE_drop這條鏈中正是匹配ipset:blk_src_ips這個地址集的,剛好有一個數(shù)據(jù)包被攔截并且丟棄,這樣已經(jīng)說明剛才的配置已經(jīng)生效了。


由于我們的日志文件可能每天會捕獲到來自不同惡意源ip地址的新記錄。我們不可能都將上面的python腳本每天都人工執(zhí)行一遍,此時可以使用crontab的任務(wù)計劃讓python腳本每天設(shè)定的時間點執(zhí)行一次,自動讓ipset規(guī)則刷新一次
通過sudo crontab -e 命令,配置如下任務(wù)計劃,讓其在每天凌晨0點開始執(zhí)行

 0 0 * * * ~/set_ip.py

小結(jié):

本案例,需要你對TCP/IP協(xié)議有一定程度的了解,以及了解firewalld內(nèi)部區(qū)域和iptables規(guī)則的內(nèi)部運行原理。你不是說主動防御嗎?是,我還沒有給出完整的示例,因為我認(rèn)為這是讀者自己需要去具體思考,你自己切實的安全方案,但我至少開了一個很好的場景示范,以及實現(xiàn)更復(fù)雜的安全需求需要用到的知識點,沒錯,Python,Python,Python重要事情說三遍,即便是從事IT服務(wù)架構(gòu)設(shè)計和運維的人員,或多或少都要涉及Linux+Python組合的復(fù)雜應(yīng)用場景,例如:。

  • 基于域名的rich規(guī)則
  • 基于域名的數(shù)據(jù)包轉(zhuǎn)發(fā)
  • 基于域名的策略路由(這條與firewalld無關(guān))

沒錯,以上是firewalld原生的規(guī)則設(shè)定無法實現(xiàn)的,但通過python寫一個封裝firewall-cmd的應(yīng)用邏輯,下面這些基于應(yīng)用層的防火墻應(yīng)用都能夠?qū)崿F(xiàn),因為通過python的第三方工具:域名解析IP的工具,多如牛毛,例如dnspython是灰常不錯的工具。上面說的這些都能夠用python寫擴展模塊來實現(xiàn)。如果你面對高并發(fā)的防火墻應(yīng)用,或需要頻繁修改firewalld動態(tài)規(guī)則/Linux內(nèi)核的動態(tài)路由表,python可能會帶來某種程度的服務(wù)器資源的性能消耗,那么別忘了還有cython來做python堅強的后盾,cython能令python的某些運算量或高I/O的邏輯能高效地執(zhí)行。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容