【问题标题】:call IPtables command within python script在 python 脚本中调用 IPtables 命令
【发布时间】:2019-12-10 15:30:56
【问题描述】:

我正在尝试在我的 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

【问题讨论】:

  • 一般提示:如果您说遇到错误,请告诉我们错误是什么。您是否以 root 权限运行此脚本?标准用户无法运行 iptables...
  • 你需要root才能调用iptables。你的 python 脚本是否以 root 权限运行?
  • 恐怕信息不够。我们也需要错误。
  • errorTraceback(最近一次调用最后一次):文件“./port_forward.py”,第 42 行,在 中 iptables = subprocess.call('iptables -I FORWARD -i eth0 -m ' +protocol+' -t'+protocol+'--dport '+port+'-j DNAT --to-destination'+ipAddress) 文件“/usr/lib/python2.7/subprocess.py”,第 493 行,调用返回Popen(*popenargs, **kwargs).wait() 文件“/usr/lib/python2.7/subprocess.py”,第 679 行,在 init 中 errread, errwrite) 文件“/usr/ lib/python2.7/subprocess.py",第 1259 行,在 _execute_child raise child_exception OSError: [Errno 2] No such file or directory

标签: python iptables


【解决方案1】:

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

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

因此,you should format your string(这也适用于 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,如 cmets 中所述: 在脚本的开头添加:

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      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 被解析为单个参数,80-j--to-destination1.2.3.4 也是如此

      【讨论】:

      • 我试图让它成为 iptables -I FORWARD -i eth0 -m TCP -t TCP --dport port -j DNAT -- to-destination 目标地址
      • 是的,我已经准确地向你展示了你在哪里犯了语法错误。
      • 是的,我将它隔开,所以现在输出将是: iptables -IFORWARD -i eth0 -m tcp -p tcp --dport 80 -j DNAT --to-destination 192.168.1.1 并且仍然错误输出
      • 您在上面粘贴的错误表明 iptables 不在任何 shell python 调用运行命令的路径中。
      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-09-04
        • 2015-12-20
        • 1970-01-01
        • 2015-10-11
        • 2018-11-08
        • 1970-01-01
        • 2022-01-18
        相关资源
        最近更新 更多