linux 当log-prefix中存在特殊字符时编程使用iptables-restore

ctehm74n  于 2023-05-06  发布在  Linux
关注(0)|答案(2)|浏览(101)

我正在编写一个程序,它可以获取iptable规则的快照,以便在以后可以恢复它们。我不想把规则写进文件;我将它们作为字符串存储在代码中。
这非常有效,调用iptables-save并将输出捕获为字符串,然后调用iptables-restore并结合bash进程替换将规则字符串反馈回iptables,例如。iptables-restore <(echo "<rules here>")(稍后必须更改此设置以使用管道,因为Ubuntu不支持)
我遇到过一个案例,其中一个规则上有一个带有空格的log-prefix选项,导致恢复步骤中断。例如:

[root@host ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
LOG        all  --  anywhere             anywhere             limit: avg 3/min burst 10 LOG level warning prefix "[UFW BLOCK] "

iptables-save的输出:

[root@host ~]# iptables-save
# Generated by iptables-save v1.8.8 (nf_tables) on Wed May  3 21:45:25 2023
*filter
:INPUT ACCEPT [101:5876]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [84:34334]
-A OUTPUT -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
COMMIT
# Completed on Wed May  3 21:45:25 2023

这是代码运行的命令:

/bin/sh -c /sbin/iptables-restore <(echo "# Generated by iptables-save v1.8.8 (nf_tables) on Wed May  3 21:45:25 2023
*filter
:INPUT ACCEPT [1936:94741]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [612:2005831]
-A OUTPUT -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
COMMIT
# Completed on Wed May  3 21:45:25 2023
")
Bad argument `BLOCK]'
Error occurred at line: 6
Try `iptables-restore -h' or 'iptables-restore --help' for more information.

如果我删除UFWBLOCK之间的空间,它就可以正常工作。
我也试过转义字符串中的引号,但仍然是同样的问题。
有什么窍门能让它工作吗。此外,我无法控制规则中的内容,它们需要完全按照快照中的内容进行替换,因此在调用restore之前预处理字符串对我不起作用。

khbbv19g

khbbv19g1#

所以看起来在办公室里的几个人反弹了这个问题之后,我实际上让它起作用了。避免引用的解决方案是正确的。\"[UFW BLOCK] \"。我以为它不工作,因为我正在监视命令的输出:

/bin/sh -c /sbin/iptables-restore <(echo "# Generated by iptables-save v1.8.8 (nf_tables) on Wed May  3 22:15:05 2023
*filter
:INPUT ACCEPT [258:20165]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [210:104923]
-A OUTPUT -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix \"[UFW BLOCK] \"
COMMIT
# Completed on Wed May  3 22:15:05 2023
")

它有转义字符,但当运行iptables list时,我看到它们不存在:

[root@host ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
LOG        all  --  anywhere             anywhere             limit: avg 3/min burst 10 LOG level warning prefix "[UFW BLOCK] "

抱歉,一时糊涂!

rryofs0p

rryofs0p2#

你没有展示任何C++代码,但你可以使用管道并使用/dev/fd/X语法,而不是依赖脆弱的bash参数处理:

int pipefd[2];
int ret = pipe(pipefd);
if (ret != 0) { /* handle error */ }
pid_t pid = fork();
if (pid != 0) {
  /* parent */
  close(pipefd[0]);
  write(pipefd[1], stored_iptables.c_str(), stored_iptables.length());
  int wstatus = 0;
  waitpid(pid, &wstatus, 0);
} else {
  /* child */
  close(pipefd[1]);
  std::string path = std::string{"/dev/fd/"} + std::to_string(pipefd[0]);
  execl("/sbin/iptables-restore", "/sbin/iptables-restore", path.c_str(), NULL);
}

为了进一步简化,您可以使用mkstemp生成一个匿名临时文件,将数据转储到其中,然后再次将/dev/fd/X传递给iptables-restore。
编辑:mkstemp解决方案(同样未经测试):

int fd = mkstemp("iptables.XXXXXX");
write(fd, stored_iptables.c_str(), stored_iptables.length());
lseek(fd, 0, SEEK_SET);
std::string path = std::string{"/dev/fd/"} + std::to_string(pipefd[0]);
execl("/sbin/iptables-restore", "/sbin/iptables-restore", path.c_str(), NULL);

相关问题