Безопасно выполнять трассировку TCP по запросу пользователя

390
turrican_34

Мне нужно выполнить трассировку TCP с использованием трассировки Linux или другого пакета, но я изо всех сил пытаюсь найти способ сделать запрос из PHP без необходимости использования привилегий sudo.

Поскольку URL будет из запроса пользователя, я не хочу использовать sudo.

Вот пример:

 $url = 'ebay.com'; $exec = 'sudo traceroute -w 1 -q 1 -T ' . $url; $escaped_command = escapeshellcmd($exec); $result = shell_exec($escaped_command);  echo $result; var_dump($result); 

Этот код работает, но только с sudoили без -T. Без sudo, он возвращает пустую строку. Без -Ttraceroute не выживают межсетевые экраны.

Если это поможет, я на ОС Centos 7.

Примечание: я не могу использовать UDP вместо TCP, потому что он часто блокируется целевым межсетевым экраном.

1
Несколько соображений при использовании escapeshellcmd () https://gist.github.com/Zenexer/40d02da5e07f151adeaeeaa11af9ab36 Daisetsu 6 лет назад 0
@schroeder: `-T` - сокращение от` -M tcp`, и этот метод задокументирован как использующий полуоткрытые соединения по умолчанию и, следовательно, нуждается в root. Это не написано явно на странице руководства, но ничего не написано о необходимых разрешениях вообще. Вероятно, с (явно не рекомендованным) параметром `tcpconn` он не будет нуждаться в root, поскольку тогда он выполняет простое` connect`. Steffen Ullrich 6 лет назад 0
Спасибо Штеффену, так что в этом случае, вероятно, можно выполнить UDP и увеличить TTL, однако отправителю необходимо прочитать ICMP, сгенерированный маршрутизаторами, поэтому в этом случае я думаю, что исходному приложению нужны корневые разрешения для чтения сгенерированного ICMP Unreach, Я думаю 6 лет назад 0
@ camp0 ОП говорит, что работает без sudo и без `-T` schroeder 6 лет назад 0
Я думаю, что @SteffenUllrich имеет окончательный ответ, и это больше вопрос Linux, чем вопрос безопасности. schroeder 6 лет назад 0
Спасибо за ответы. Похоже, что невозможно выполнить трассировку TCP без sudo. Команда `$ exec = 'traceroute -w 1 -q 1'. $ url; `отлично работает без sudo (с использованием UDP), так что я думаю, это так или ничего ... turrican_34 6 лет назад 0

1 ответ на вопрос

0
harrymc

Вы не можете запустить sudo из PHP, так как Apache не позволит вам сделать это по соображениям безопасности. Вам нужно реализовать traceroute в PHP внутри вашего кода.

Есть несколько таких реализаций, которые можно найти в открытом доступе.

Смотрите, например:

Создание программы traceroute на PHP, код доступен на github .


Другой подход, позволяющий избежать sudo для traceroute, основан на том факте, что traceroute не должен запускаться с правами root; это просто нуждается в способности CAP_NET_ADMIN. Чтобы установить это как файловую возможность для всех пользователей, если ваше ядро ​​поддерживает файловые возможности, а модуль безопасности Linux (SELinux, AppArmor) не блокирует его:

setcap CAP_NET_ADMIN+ep /usr/sbin/traceroute 

Код PHP может быть очень простым, используя popen():

$handle = popen("traceroute www.xxx.com 2>&1", "r"); while(!feof($handle)) { $buffer = fgets($handle); $buffer = "<p>".$buffer."</p>\n"; echo $buffer; } pclose($handle); 
Я использую Nginx, поэтому могу запускать sudo, но это небезопасно. Реализация PHP, которую вы связали, также требует sudo и использует UDP, а не TCP, что мне и нужно. , turrican_34 6 лет назад 0
Как человек из Nginx, возможно, вы сможете объяснить мне, почему sudo необходимо для отправки сообщений через сокеты. harrymc 6 лет назад 0
В соответствии с потоком SO, который я обнаружил * Открытие необработанного сокета позволяет читать все, что получено в данном интерфейсе, поэтому, в принципе, вы можете прочитать любой пакет, направленный в любое приложение, даже если это приложение принадлежит другому пользователю. В основном это означает, что пользователь с этой возможностью может читать любые сообщения всех пользователей. *. https://stackoverflow.com/questions/4404860/raw-sockets-need-root-priviliege turrican_34 6 лет назад 0
Правильно, поэтому я добавил другой подход. harrymc 6 лет назад 0
Это сделал это! Благодарю. Как ни странно, мне не нужен `cap_net_admin`, он работал только с` cap_net_raw`, как `sudo setcap cap_net_raw + ep / usr / bin / traceroute`. Если я запускаю `getcap / usr / bin / traceroute`, я получаю` / usr / bin / traceroute = cap_net_raw + ep`. В данный момент у меня есть selinux в разрешающем режиме, поэтому, когда я его включу, думаю, у меня будут проблемы, которые нужно исправить. turrican_34 6 лет назад 0