0

我试图在我的 python 脚本中调用以下命令。我正在尝试将规则插入 IP 表。我正在使用子进程来调用它并在需要的地方插入变量,但是我遇到了一个很大的错误。有什么建议么?

iptables = subprocess.call('iptables -I FORWARD -eth 0 -m '+protocol+' -t'+protocol+'--dport '+port+'-j DNAT --to-destination'+ipAddress)

错误:

Traceback (most recent call last):
  File "./port_forward.py", line 42, in <module>
    iptables = subprocess.call('iptables -I FORWARD -i eth0 -m '+protocol+' -t'+protocol+'--dport '+port+'-j DNAT --to-destination'+ipAddress)
  File "/usr/lib/python2.7/subprocess.py", line 493, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.7/subprocess.py", line 679, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1259, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
4

4 回答 4

3

您的问题对于 Python 初学者来说很常见。您尝试通过连接许多字符串和变量来构建复杂的字符串,而不是格式化字符串命令。相反,使用字符串格式,它将允许您测试您的命令并使您的代码更具可读性和灵活性。

您的原始字符串在选项和参数之间缺少空格,例如--to-destination1.2.3.4.

因此,您应该格式化您的字符串(这也适用于 python 2.7):

opts = {'iptables': '/sbin/iptables', 'protocol': 'tcp', 'port': 80, 'ipAddress': '0.0.0.0'}
ipcmd = '{iptables} -I FORWARD -eth 0 -m {protocol} -t {protocol} \
--dport {port} -j DNAT --to-destination  {ipAddress}'.format(**opts)

if DEBUG:
   print ipcmd
iptables = subprocess.call(ipcmd)

这在以后更容易修改,而且,当你进行更多的 Python 编程时,你会发现它更具可读性。

此外,要调用 IPTables,您应该是 root,如评论中所述:在脚本的开头添加:

   import sys
   import os
   if not os.getuid() == 0:
        print "You must be root to change IPTables."
        sys.exit(2)

看到您的错误跟踪后更新:

您正在尝试调用命令iptables,但它不在您的路径中。您应该调用 iptables 的完整路径,例如/sbin/iptables

于 2013-07-23T20:25:21.817 回答
1

我以同样的方式编写了一个简单的防火墙并意识到,“为什么不直接用 bash 编写呢?”。无论如何,我发现了 python-iptables 库并使用它重写了我的代码。我建议检查一下。我认为它会给你一种更健壮和结构化的方式来编写 iptables 规则。

于 2013-12-28T05:33:31.563 回答
0

由于缺少空格,您的命令充满了语法错误,如下所示:

iptables = subprocess.call(
     'iptables -I FORWARD -eth 0 -m '
   + protocol
   + ' -t'+protocol
         ^---here
   + '--dport '
      ^-- here
   + port
   + '-j DNAT --to-destination'
      ^--here
   + ipAddress)
     ^---here

生成后,您的 iptables 行将如下所示

-ttcp--dport 80-j DNAT  --to-destination1.2.3.4

-ttcp--dport被解析为 SINGLE 参数,同样适用于80-j--to-destination1.2.3.4

于 2013-07-23T19:45:46.153 回答
0

只需将参数 shell=True 与命令一起传递。

iptables = subprocess.call('iptables -I FORWARD -eth 0 -m '+protocol+' -t'+protocol+'--dport '+port+'-j DNAT --to-destination'+ipAddress, shell=True)
于 2019-12-10T07:30:56.123 回答