如何用go操作iptables和ipset設(shè)置黑白名單
1、背景
iptables是linux中一個比較好用的防火墻工具,可以通過它對網(wǎng)絡(luò)數(shù)據(jù)包進(jìn)行管理和過濾,iptables中的四表五鏈在網(wǎng)上能查到很多文章解釋,這里不做過多解釋。
ipset是一個用于管理IP地址集合的工具,能和iptables組合起來一起使用,方便維護(hù)和管理各種防火墻規(guī)則。
本文會給出一個通過go庫操作iptables中filter表的INPUT鏈和ipset來實(shí)現(xiàn)允許和拒絕進(jìn)入本機(jī)ipv4網(wǎng)絡(luò)數(shù)據(jù)包的示例。
2、go庫下載
【1】iptables下載
go get -u github.com/coreos/go-iptables
【2】ipset下載
go get -u github.com/vishvananda/netlink
3、go庫和命令行對比
操作方式 | 優(yōu)點(diǎn) | 缺點(diǎn) |
---|---|---|
命令行操作 | 簡單方便 | 平臺架構(gòu)版本兼容性差,復(fù)雜場景靈活性差 |
go庫操作 | 平臺兼容性強(qiáng),復(fù)雜場景靈活性高 | 需要花時間驗(yàn)證庫的正確性 |
4、代碼示例
【1】定義iptables規(guī)則和ipset集合名稱常量
// ipset類型 const ( HASH_IP = "hash:ip" HASH_IP_PORT = "hash:ip,port" HASH_NET = "hash:net" HASH_NET_PORT = "hash:net,port" ) // ipset名稱 const ( WL_IP = "wl_ip" WL_IP_PORT = "wl_ip_port" WL_NET = "wl_net" WL_NET_PORT = "wl_net_port" BL_IP = "bl_ip" BL_IP_PORT = "bl_ip_port" BL_NET = "bl_net" BL_NET_PORT = "bl_net_port" ) var ipSetNameToTypeMp = map[string]string{ WL_IP: HASH_IP, WL_IP_PORT: HASH_IP_PORT, WL_NET: HASH_NET, WL_NET_PORT: HASH_NET_PORT, BL_IP: HASH_IP, BL_IP_PORT: HASH_IP_PORT, BL_NET: HASH_NET, BL_NET_PORT: HASH_NET_PORT, } // iptables規(guī)則 var iptRules = [][]string{ {"-m", "state", "--state", "ESTABLISHED,RELATED", "-j", "ACCEPT"}, //已建連接允許 {"-i", "lo", "-j", "ACCEPT"}, //本地回環(huán)包運(yùn)行 {"-m", "set", "--match-set", WL_IP, "src", "-j", "ACCEPT"}, //對集合條目里的源ip允許 {"-m", "set", "--match-set", WL_IP_PORT, "src,dst", "-j", "ACCEPT"}, //對集合條目里的源ip和目的port允許 {"-m", "set", "--match-set", WL_NET, "src", "-j", "ACCEPT"}, //對集合條目里的源ip允許 {"-m", "set", "--match-set", WL_NET_PORT, "src,dst", "-j", "ACCEPT"}, //對集合條目里的源ip和目的port允許 {"-m", "set", "--match-set", BL_IP, "src", "-j", "ACCEPT"}, //對集合條目里的源ip拒絕 {"-m", "set", "--match-set", BL_IP_PORT, "src,dst", "-j", "ACCEPT"}, //對集合條目里的源ip和目的port拒絕 {"-m", "set", "--match-set", BL_NET, "src", "-j", "ACCEPT"}, //對集合條目里的源ip拒絕 {"-m", "set", "--match-set", BL_NET_PORT, "src,dst", "-j", "ACCEPT"}, //對集合條目里的源ip和目的port拒絕 }
一般都會對本機(jī)的已建連接和lo網(wǎng)口的數(shù)據(jù)包放行,兩條規(guī)則分別為:
1、iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 2、iptables -A INPUT -i lo -j ACCEPT
默認(rèn)在filter表上增加規(guī)則,也可以增加-t指定其它表
【2】創(chuàng)建ipset集合
//創(chuàng)建ipset集合 for setName, setType := range ipSetNameToTypeMp { if err := netlink.IpsetCreate(setName, setType, netlink.IpsetCreateOptions{Replace: true}); err != nil { logger.Error("ipset create error", zap.String("set_name", setName), zap.Error(err)) continue } }
netlink.IpsetCreateOptions中可以定義其它自定義參數(shù),比如:超時時間、ipv4/ipv6、最大個數(shù)、是否覆蓋已存在的集合等。
【3】創(chuàng)建iptables規(guī)則
//創(chuàng)建iptables規(guī)則 ipt, err := iptables.New() if err != nil { logger.Error("iptables new error", zap.Error(err)) return } for _, iptRule := range iptRules { if err = ipt.AppendUnique("filter", "INPUT", iptRule...); err != nil { logger.Error("iptables append unique error", zap.Error(err)) continue } }
AppendUnique函數(shù)是往指定鏈中追加規(guī)則,如果規(guī)則存在就不會去做操作。
【4】添加條目
//增加ipset條目 var port = uint16(100) if err = netlink.IpsetAdd(WL_IP, &netlink.IPSetEntry{IP: net.ParseIP("1.1.1.1")}); err != nil { //對源ip為1.1.1.1的包加白 logger.Error("ipset add error", zap.Error(err)) } if err = netlink.IpsetAdd(WL_IP_PORT, &netlink.IPSetEntry{IP: net.ParseIP("2.2.2.2"), Port: &port}); err != nil { //對源ip為2.2.2.2,目的端口為100的包加白 logger.Error("ipset add error", zap.Error(err)) } if err = netlink.IpsetAdd(WL_NET, &netlink.IPSetEntry{IP: net.ParseIP("3.3.3.3"), CIDR: 24}); err != nil { //對源ip在3.3.3.3/24范圍內(nèi)的包加白 logger.Error("ipset add error", zap.Error(err)) } if err = netlink.IpsetAdd(WL_NET_PORT, &netlink.IPSetEntry{IP: net.ParseIP("4.4.4.4"), CIDR: 24, Port: &port}); err != nil { //對源在4.4.4.4/24范圍內(nèi),目的端口為100的包加白 logger.Error("ipset add error", zap.Error(err)) } if err = netlink.IpsetAdd(BL_IP, &netlink.IPSetEntry{IP: net.ParseIP("5.5.5.5")}); err != nil { //對源ip為1.1.1.1的包加黑 logger.Error("ipset add error", zap.Error(err)) } if err = netlink.IpsetAdd(BL_IP_PORT, &netlink.IPSetEntry{IP: net.ParseIP("6.6.6.6"), Port: &port}); err != nil { //對源ip為2.2.2.2,目的端口為100的包加黑 logger.Error("ipset add error", zap.Error(err)) } if err = netlink.IpsetAdd(BL_NET, &netlink.IPSetEntry{IP: net.ParseIP("7.7.7.7"), CIDR: 24}); err != nil { //對源ip在3.3.3.3/24范圍內(nèi)的包加黑 logger.Error("ipset add error", zap.Error(err)) } if err = netlink.IpsetAdd(BL_NET_PORT, &netlink.IPSetEntry{IP: net.ParseIP("8.8.8.8"), CIDR: 24, Port: &port}); err != nil { //對源在4.4.4.4/24范圍內(nèi),目的端口為100的包加黑 logger.Error("ipset add error", zap.Error(err)) }
根據(jù)不同的集合類型給netlink.IPSetEntry設(shè)置不同的參數(shù)。
【5】查看iptables
[root@xxx ~]# iptables -nL INPUT Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 match-set wl_ip src ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 match-set wl_ip_port src,dst ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 match-set wl_net src ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 match-set wl_net_port src,dst ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 match-set bl_ip src ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 match-set bl_ip_port src,dst ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 match-set bl_net src ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 match-set bl_net_port src,dst [root@xxx ~]# iptables -S | grep INPUT -P INPUT ACCEPT -N SPA_HIDE_INPUT -N SPA_WL_INPUT -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -m set --match-set wl_ip src -j ACCEPT -A INPUT -m set --match-set wl_ip_port src,dst -j ACCEPT -A INPUT -m set --match-set wl_net src -j ACCEPT -A INPUT -m set --match-set wl_net_port src,dst -j ACCEPT -A INPUT -m set --match-set bl_ip src -j ACCEPT -A INPUT -m set --match-set bl_ip_port src,dst -j ACCEPT -A INPUT -m set --match-set bl_net src -j ACCEPT -A INPUT -m set --match-set bl_net_port src,dst -j ACCEPT
【6】查看ipset
[root@xxx ~]# ipset list Name: bl_ip Type: hash:ip Revision: 0 Header: family inet hashsize 1024 maxelem 65536 Size in memory: 16544 References: 1 Members: 5.5.5.5 Name: bl_ip_port Type: hash:ip,port Revision: 1 Header: family inet hashsize 1024 maxelem 65536 Size in memory: 16560 References: 1 Members: 6.6.6.6,tcp:100 Name: bl_net Type: hash:net Revision: 0 Header: family inet hashsize 1024 maxelem 65536 Size in memory: 16816 References: 1 Members: 7.7.7.0/24 Name: bl_net_port Type: hash:net,port Revision: 1 Header: family inet hashsize 1024 maxelem 65536 Size in memory: 16816 References: 1 Members: 8.8.8.0/24,tcp:100 Name: wl_ip Type: hash:ip Revision: 0 Header: family inet hashsize 1024 maxelem 65536 Size in memory: 16544 References: 1 Members: 1.1.1.1 Name: wl_ip_port Type: hash:ip,port Revision: 1 Header: family inet hashsize 1024 maxelem 65536 Size in memory: 16560 References: 1 Members: 2.2.2.2,tcp:100 Name: wl_net Type: hash:net Revision: 0 Header: family inet hashsize 1024 maxelem 65536 Size in memory: 16816 References: 1 Members: 3.3.3.0/24 Name: wl_net_port Type: hash:net,port Revision: 1 Header: family inet hashsize 1024 maxelem 65536 Size in memory: 16816 References: 1 Members: 4.4.4.0/24,tcp:100
5、總結(jié)
上面給出了一部分go的iptables和ipset庫的基礎(chǔ)用法,在真實(shí)的業(yè)務(wù)場景中是可以做出很多優(yōu)化,比如:黑白名單各自定義一條自定義鏈再追加到INPUT鏈去維護(hù),這樣黑白名單相互之間不會互相影響。
更多功能可以根據(jù)庫里的API應(yīng)用到適合的場景。
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
一鍵定位Golang線上服務(wù)內(nèi)存泄露的秘籍
內(nèi)存泄露?別讓它拖垮你的Golang線上服務(wù)!快速掌握Go語言服務(wù)內(nèi)存泄漏排查秘籍,從此問題無處遁形,一文讀懂如何精準(zhǔn)定位與有效解決Golang應(yīng)用中的內(nèi)存問題,立即閱讀,讓性能飛升!2024-01-01Windows+Linux系統(tǒng)下Go語言環(huán)境安裝配置過程
Go 語言被設(shè)計成一門應(yīng)用于搭載 Web 服務(wù)器,存儲集群或類似用途的巨型中央服務(wù)器的系統(tǒng)編程語言。這篇文章主要介紹了Windows+Linux系統(tǒng)下Go語言環(huán)境搭建配置過程,針對每種系統(tǒng)給大家講解的非常詳細(xì),需要的朋友可以參考下2021-06-06Go type關(guān)鍵字(類型定義與類型別名的使用差異)用法實(shí)例探究
這篇文章主要為大家介紹了Go type關(guān)鍵字(類型定義與類型別名的使用差異)用法實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01?Go?語言實(shí)現(xiàn)?HTTP?文件上傳和下載
這篇文章主要介紹了Go語言實(shí)現(xiàn)HTTP文件上傳和下載,文章圍繞主題展開詳細(xì)的內(nèi)容戒殺,具有一定的參考價值,需要的小伙伴可以參考一下2022-09-09Go語言實(shí)現(xiàn)請求超時處理的方法總結(jié)
這篇文章主要為大家詳細(xì)介紹了Go語言中實(shí)現(xiàn)請求的超時控制的方法,主要是通過timer和timerCtx來實(shí)現(xiàn)請求的超時控制,希望對大家有所幫助2023-05-05go語言實(shí)現(xiàn)短信發(fā)送實(shí)例探究
這篇文章主要為大家介紹了go語言實(shí)現(xiàn)短信發(fā)送實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01