PHP exec(iptables --help) 有效,但 exec(iptables --command) 无效

PHP exec(iptables --help) 有效,但 exec(iptables --command) 无效

PHP 7.3.33我想Apache 2.4从 PHP(Web 服务器环境)运行 iptables 来阻止/取消阻止 IP,从命令行,这可以正常工作:

/usr/sbin/iptables --insert INPUT --source example.com --jump DROP

但如果我尝试从 PHP 使用以下代码:

exec('/usr/sbin/iptables --insert INPUT --source example.com --jump DROP', $return);
print_r($return);

我得到一个空白结果并且没有添加 iptables 规则:

Array
(
)

但是,iptables 路径似乎正确,并且 iptables 运行,因为该--help命令返回内容,那么为什么上述命令不起作用呢?

exec('/usr/sbin/iptables --help', $return);
print_r($return);
Array
(
    [0] => iptables v1.8.4
    [1] => 
    [2] => Usage: iptables -[ACD] chain rule-specification [options]
    [3] =>  iptables -I chain [rulenum] rule-specification [options]
    [4] =>  iptables -R chain rulenum rule-specification [options]
    [5] =>  iptables -D chain rulenum [options]
    [6] =>  iptables -[LS] [chain [rulenum]] [options]
    [7] =>  iptables -[FZ] [chain] [options]
    [8] =>  iptables -[NX] chain
    [9] =>  iptables -E old-chain-name new-chain-name
    [10] =>     iptables -P chain target [options]
    [11] =>     iptables -h (print this help information)
    [12] => 
    [13] => Commands:
    [14] => Either long or short options are allowed.
    [15] =>   --append  -A chain        Append to chain
    [16] =>   --check   -C chain        Check for the existence of a rule
    [17] =>   --delete  -D chain        Delete matching rule from chain
    [18] =>   --delete  -D chain rulenum
    [19] =>                 Delete rule rulenum (1 = first) from chain
    [20] =>   --insert  -I chain [rulenum]
    [21] =>                 Insert in chain as rulenum (default 1=first)
    [22] =>   --replace -R chain rulenum
    [23] =>                 Replace rule rulenum (1 = first) in chain
    [24] =>   --list    -L [chain [rulenum]]
    [25] =>                 List the rules in a chain or all chains
    [26] =>   --list-rules -S [chain [rulenum]]
    [27] =>                 Print the rules in a chain or all chains
    [28] =>   --flush   -F [chain]      Delete all rules in  chain or all chains
    [29] =>   --zero    -Z [chain [rulenum]]
    [30] =>                 Zero counters in chain or all chains
    [31] =>   --new     -N chain        Create a new user-defined chain
    [32] =>   --delete-chain
    [33] =>          -X [chain]     Delete a user-defined chain
    [34] =>   --policy  -P chain target
    [35] =>                 Change policy on chain to target
    [36] =>   --rename-chain
    [37] =>          -E old-chain new-chain
    [38] =>                 Change chain name, (moving any references)
    [39] => Options:
    [40] =>     --ipv4  -4      Nothing (line is ignored by ip6tables-restore)
    [41] =>     --ipv6  -6      Error (line is ignored by iptables-restore)
    [42] => [!] --proto -p proto    protocol: by number or name, eg. `tcp'
    [43] => [!] --source    -s address[/mask][...]
    [44] =>                 source specification
    [45] => [!] --destination -d address[/mask][...]
    [46] =>                 destination specification
    [47] => [!] --in-interface -i input name[+]
    [48] =>                 network interface name ([+] for wildcard)
    [49] =>  --jump -j target
    [50] =>                 target for rule (may load target extension)
    [51] =>   --goto      -g chain
    [52] =>                    jump to chain with no return
    [53] =>   --match   -m match
    [54] =>                 extended match (may load extension)
    [55] =>   --numeric -n      numeric output of addresses and ports
    [56] => [!] --out-interface -o output name[+]
    [57] =>                 network interface name ([+] for wildcard)
    [58] =>   --table   -t table    table to manipulate (default: `filter')
    [59] =>   --verbose -v      verbose mode
    [60] =>   --wait    -w [seconds]    maximum wait to acquire xtables lock before give up
    [61] =>   --wait-interval -W [usecs]    wait time to try to acquire xtables lock
    [62] =>                 default is 1 second
    [63] =>   --line-numbers        print line numbers when listing
    [64] =>   --exact   -x      expand numbers (display exact values)
    [65] => [!] --fragment  -f      match second or further fragments only
    [66] =>   --modprobe=<command>      try to insert modules using this command
    [67] =>   --set-counters PKTS BYTES set the counter during insert/append
    [68] => [!] --version   -V      print package version.
)

答案1

您以什么用户身份运行该iptables命令?如果您iptables以非 root 用户身份运行,它将打印一条错误消息stderr并返回错误代码,但是当您写入:

exec('/usr/sbin/iptables --insert INPUT --source example.com --jump DROP', $return);

您 (a) 仅捕获stdout并且 (b) 您没有检查错误代码。如果我从命令行以 运行该代码,则该代码对我来说运行良好。例如root,如果iptables.php我有以下内容:

<?php

exec('iptables --insert INPUT --source example.com --jump DROP', $output, $retval);
echo "return code: $retval\n";
echo "output:\n";
print_r($output);
?>

我得到的输出是:

return code: 0
output:
Array
(
)

我看到规则已经创建:

# iptables -S INPUT
-P INPUT ACCEPT
-A INPUT -s 93.184.216.34/32 -j DROP

但如果我以非 root 用户身份运行同样的事情:

$ php iptables.php
iptables v1.8.8 (nf_tables): Could not fetch rule set generation id: Permission denied (you must be root)

return code: 4
output:
Array
(
)

请注意,错误消息直接打印在控制台上,并且不是被 PHP 捕获,所以我们看到一个空的输出数组——但是我们查看错误返回代码。根据您运行代码的方式,您可能无法看到错误消息(如果您通过 Web 服务器运行此代码,错误消息可能会显示在服务器错误日志中)。

相关内容