通过bash在iptables中自动化白名单ip地址

时间:2012-12-25 09:02:12

标签: python linux bash iptables

我正在寻找将白名单IP地址自动化为iptables的最佳方法。 IP地址和端口列表来自JSON文件/accept-rules.json,其格式如下:

[
  {
    "ip": "1.2.3.4",
    "cidr": 32,
    "protocol": "tcp",
    "port": 3306
  },
  {
    "ip": "2.4.5.6",
    "cidr": 32,
    "protocol": "tcp",
    "port": 80
  },
  {
    "ip": "5.6.7.8",
    "cidr": 32,
    "protocol": "tcp",
    "port": 443
  },
  {
    "ip": "6.8.3.1",
    "cidr": 32,
    "protocol": "tcp",
    "port": 53
  }
]

我需要一个bashpython脚本来读取json文件并创建ACCEPT iptables规则。基于上面ACCEPT的示例json规则应如下所示:

iptables -A INPUT -s 1.2.3.4/32 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -A INPUT -s 2.4.5.6/32 -p tcp -m tcp --dport 80 -j ACCEPT
iptables -A INPUT -s 5.6.7.8/32 -p tcp -m tcp --dport 443 -j ACCEPT
iptables -A INPUT -s 6.8.3.1/32 -p tcp -m tcp --dport 53 -j ACCEPT

对这个代码进行编码的最佳方法有什么想法吗?

5 个答案:

答案 0 :(得分:1)

这是一个python代码:

这将生成一个包含所有iptable条目的bash脚本文件'accept.sh'。

# accept.py

fp = open("accept-rules.json", "r")

data = fp.readlines()
fp1 = open("accept.sh", "w")

for line in data:

    if "{" in line:
        datum = {}
    elif "}" in line:
        s = "iptables -A INPUT -s " + datum["ip"] + "/" + datum["cidr"] + " -p " + datum["protocol"] + " -m " + datum["protocol"] + " --dport " + datum["port"] + " -j ACCEPT\n"
        fp1.write(s)
    elif "[" in line or "]" in line:
        continue
    else:
        datum[line.split(":")[0].strip().strip('"')] = line.split(":")[1].strip().strip(",").strip('"')

fp1.close()
fp.close()

答案 1 :(得分:1)

请注意iptables -A将规则添加到表的末尾。匹配规则时,iptables从上到下工作,第一个匹配获胜,如果您之前已阻止某个地址,那么使用-A将其列为白色将无法正常工作(许多默认规则集都有一个blaket拒绝全部为示例)在这种情况下,最好使用iptables -I在开头插入规则。

#!/bin/bash

function getval {
    set -- $1
    RET=${2//[\",]/}
}
while read line
    do
        set -- $line
        if [[ "$1" == '"ip":' ]]
            then
                getval "$line"
                IPADDRESS=$RET
                read line
                getval "$line"
                CIDR=$RET
                read line
                getval  "$line"
                PROTOCOL=$RET
                read line
                getval "$line"
                PORT=$RET
                /sbin/iptables  -I INPUT -s "$IPADDRESS"/"$CIDR" -p "$PROTOCOL" -m "$PROTOCOL" --dport "$PORT" -j ACCEPT
             fi
    done <file.json

答案 2 :(得分:1)

有一个更干净的纯bash 版本。 (没有eval

declare -A iptArray
iptArray[action]='A'
getval() {
    [[ "$@" =~  \"([^\*]*)\"\ *:\ *\"?([^\",]*)\"?[,\ ]*$ ]] && \
        iptArray[${BASH_REMATCH[1]}]=${BASH_REMATCH[2]}
}
while read line;do
    getval $line
    [[ "$line" =~ } ]] && \
        echo iptables -${iptArray[action]} INPUT -p ${iptArray[protocol]} \
            -s ${iptArray[ip]}/${iptArray[cidr]} \
            --dport ${iptArray[port]} -j ACCEPT
  done < ipt_whitelist.json 
iptables -A INPUT -p tcp -s 1.2.3.4/32 --dport 3306 -j ACCEPT
iptables -A INPUT -p tcp -s 2.4.5.6/32 --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -s 5.6.7.8/32 --dport 443 -j ACCEPT
iptables -A INPUT -p tcp -s 6.8.3.1/32 --dport 53 -j ACCEPT

(删除echo以执行操作而不是仅打印它)

答案 3 :(得分:1)

更简洁的Python版本:

#!/usr/bin/env python
import json
import sys

for rule in json.load(sys.stdin):
    print("iptables -I INPUT -s {ip}/{cidr} -p {protocol} "
          "-m {protocol} --dport {port} -j ACCEPT".format(**rule))

注意:它使用-I在开头插入规则。

实施例

$ json2iptables < accept-rules.json

Output

iptables -I INPUT -s 1.2.3.4/32 -p tcp -m tcp --dport 3306 -j ACCEPT
iptables -I INPUT -s 2.4.5.6/32 -p tcp -m tcp --dport 80 -j ACCEPT
iptables -I INPUT -s 5.6.7.8/32 -p tcp -m tcp --dport 443 -j ACCEPT
iptables -I INPUT -s 6.8.3.1/32 -p tcp -m tcp --dport 53 -j ACCEPT

答案 4 :(得分:0)

Python实现:

import json
rules_file = open('accept-rules.json', 'r')
rules = json.load(rules_file)
rules_file.close()
iptables = open('iptavles.sh', 'w')
for rule in rules:
    rule_str = 'iptables -A INPUT -s %s/%s -p tcp -m %s --dport %s -j ACCEPT\n' % (rule['ip'], rule['cidr'], rule['protocol'], rule['port'])
    iptables.write(rule_str)
iptables.close()

accept-rules.json - 启动json文件, iptables.sh - 目标文件