2

1.文件

一个文件/etc/ssh/ipblock包含如下所示的行:

2012-01-01 12:00 192.0.2.201
2012-01-01 14:15 198.51.100.123
2012-02-15 09:45 192.0.2.15
2012-03-12 21:45 192.0.2.14
2012-04-25 00:15 203.0.113.243

2. 命令

该命令的输出iptables -nL somechain如下所示:

链 somechain (2 参考)
目标 prot opt 源目标
DROP all -- 172.18.1.4 任何地方
DROP all -- 198.51.100.123 任何地方
DROP all -- 172.20.4.16 任何地方
DROP all -- 192.0.2.125 任何地方
DROP all -- 172.21.1.2 任何地方

3. 手头的任务

  1. 首先,我想获取 iptables 链(字段 4)中存在但文件中不存在的 IP 地址列表 A。
  2. 然后我想获取文件中存在但不在 iptables 链中的 IP 地址列表 B。
  3. 列表 A 中的 IP 地址应以相同的样式(日期、时间、IP)附加到文件中
  4. 然后应将列表 B 中的 IP 地址添加到 iptables 链中
    iptables -A somechain -d IP -j DROP

4. 背景

我希望扩展我的 awk-fu,所以我一直试图让它与一个可以在没有参数的情况下执行的 awk 脚本一起工作。但我失败了。

我知道我可以使用命令从命令中获取输出,getline因此我能够以这种方式获取时间和日期。而且我也知道可以使用getline foo < file. 但是我只有多次失败的尝试将这一切组合成一个工作的 awk 脚本。

我意识到我可以让它与其他编程语言或 shell 脚本一起工作。但这可以通过无需参数即可运行的 awk 脚本来完成吗?

4

2 回答 2

3

我认为这几乎正是您想要的。这项工作是否都在一个文件中,我猜代码几乎是不言自明的......
易于适应,可扩展......

用法:
./foo.awk CHAIN ip.file

foo.awk:

#!/usr/bin/awk -f
BEGIN {
    CHAIN= ARGV[1]
    IPBLOCKFILE = ARGV[2]

    while((getline < IPBLOCKFILE) > 0) {
        IPBLOCK[$3] = 1
    }

    command = "iptables -nL " CHAIN
    command |getline
    command |getline
    while((command |getline) > 0) {
        IPTABLES[$4] = 1
    }
    close(command)

    print "not in IPBLOCK (will be appended):"
    command = "date +'%Y-%m-%d %H:%M'"
    command |getline DATE
    close(command)
    for(ip in IPTABLES) {
        if(!IPBLOCK[ip]) {
            print ip
            print DATE,ip >> IPBLOCKFILE
        }
    }

    print "not in IPTABLES (will be appended):"
    # command = "echo iptables -A " CHAIN " -s " //use for testing 
    command = "iptables -A " CHAIN " -s "
    for(ip in IPBLOCK) {
        if(!IPTABLES[ip]) {
            print ip
            system(command ip " -j DROP")
        }
    }
    exit
}
于 2012-08-04T17:08:44.397 回答
1

做1&3:

comm -13 <(awk '{print $3}' /etc/ssh/ipblock | sort) <(iptables -nL somechain | awk '/\./{print $4}' | sort) | xargs -n 1 echo `date '+%y-%m-%d %H:%M'` >> /etc/ipblock

做2&4:

comm -13 <(awk '{print $3}' /etc/ssh/ipblock | sort) <(iptables -nL somechain | awk '/\./{print $4}' | sort) | xargs -n 1 iptables -A somechain -d IP -j DROP

该命令由以下构建块构成:

  1. Bash 进程替换功能:它有点类似于管道功能,但通常在程序在其参数/选项中需要两个或多个输入文件时使用。Bash 创建fifo文件,该文件基本上“包含”给定命令的输出。在我们的例子中,输出将是 ip 地址。
  2. 然后将awk脚本的输出传递给comm程序,这两个awk脚本都非常简单:它们只是打印 IP 地址。在第一种情况下,所有 ips 都包含在第三列中(因此$3),在第二种情况下,所有 ips 都包含在第四列中,但是必须去掉列标题(“destination”字符串),所以使用简单的正则表达式/\./:它过滤掉所有不包含点的字符串。
  3. comm需要对两个输入进行排序,因此输出的awk排序使用sort
  4. 现在comm程序接收到两个 IP 地址列表。如果没有给出选项,它会打印三列:FILE1 唯一的行、FILE2 唯一的行、两个文件中的行。通过传递-23给它,我们只得到 FILE1 独有的行。类似地,传递-13使其输出 FILE2 独有的行。
  5. xargs基本上是 bash 中的“foreach”循环,它对每个输入行执行一个给定的命令(感谢-n 1)。第二个非常明显(这是所需的iptables调用)。第二个也不复杂:它只date是以正确的格式输出当前时间。
于 2012-08-04T16:16:38.533 回答