PHP exec(iptables —help) работает, но exec(iptables —command) не работает

В PHP 7.3.33 и Apache 2.4 Я хочу запустить iptables из PHP (среда веб-сервера), чтобы заблокировать/разблокировать 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 ответ
1

Под каким пользователем вы работаете iptables команда? Если вы запустите iptables как пользователь без полномочий root, он выведет сообщение об ошибке на stderr и вернуть код ошибки, но когда вы пишете:

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

Вы (а) только захватываете stdout и (б) вы не проверяете код ошибки. Этот код отлично работает для меня, если я запускаю его из командной строки как 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
(
)

Обратите внимание, что сообщение об ошибке было напечатано непосредственно на консоли и не было cpatped PHP, поэтому мы видим пустой выходной массив, но мы делать см. код возврата ошибки. В зависимости от того, как вы запускаете код, вы можете не увидеть сообщение об ошибке (если вы запускаете это через веб-сервер, сообщение об ошибке может отображаться в журналах ошибок сервера).

жаворонки

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *