#linux #bash #shell #dns
Задание: Выведите IP адрес под которым машина отправляет запросы к 8.8.8.8 (учитывать NAT после выхода пакета из машины не нужно, нужен IP адрес с которым пакет покидает машину). Нужно написать Bash-скрипт. Как я понимаю, нужно понять где у нас в локальной сети шлюз. На данный момент готово следующее: используем tcpdump - tcpdump -i any 'udp port 53' > whoIP - таким образом результат дампа со всеми запросами на 53 порт(т.е. DNS) сохраняется в файл. Файл содержит следующие строки: 15:09:44.365818 IP 192.168.0.102.11996 > 192.168.0.1.domain: 31675+ A? www.google-analytics.com. (42) 15:09:44.398267 IP 192.168.0.1.domain > 192.168.0.102.11996: 31675 7/0/0 CNAME www-google-analytics.l.google.com., A затем при помощи "Адского" выражения: cat whoIP | grep A? | grep -E -o '>+ ([0-9]{1,3}[.]){3}[0-9]{1,3}'| grep -E -o "([0-9]{1,3}[.]){3}[0-9]{1,3}" Логика его такова: cat whoIP |grep A? - в файле мы ищем строки содержащие запрос на разрешении имени. tcpdump помечает такие строки A? | grep -E -o '>+ ([0-9]{1,3}[.]){3}[0-9]{1,3}' - данное регулярное выражение ищет IP-адрес в формате ipv4. в строке мы ищем следующую конструкцию "> "ipv4 адрес"" - в tcpdump ">" означает от кого к кому идет запрос. Нас интересует к кому. | grep -E -o "([0-9]{1,3}[.]){3}[0-9]{1,3}" - из найденного фрагмента "к кому" вырезаем только адрес.Данное выражение от предыдущего отличается лишь отсутствием "<" В целом мой алгоритм следующий: 1.Запустить tcpdump и перенаправить его вывод в файл whoIP Послать в другом терминал DNS-запрос при помощи dig ОСТАНОВИТЬ TCPDUMP ctrl+c grep файл Во-первых, проблема в том, что в скрипт данную последовательность я заложить не могу, т.к. tcpdump работает пока ему не послать сигнал завершения( вот тут и загвоздка). Если в скрипте ищет запуск tcpdump, то следующие команды не исполняются, т.к. tcpdump работает бесконечно. Подскажите, можно ли написать данный скрипт и вообще иду ли я по верному пути, в чем сомневаюсь очень сильно. Мне кажется, должно быть более простое решение.
Ответы
Ответ 1
Если это работает, то значит имеет право на жизнь. А tcpdump можно заставить работать как нужно. для начала нужно его запустить в фоне tcpdump .... параметры .... & символ & важен - он отправляет процесс в фон и можно будет продолжить скрипт дальше. Так как нам нужно будет потом его остановить, то следующей строкой запоминаем его pid. TDPID=$! эта строка должна быть сразу. Иначе она запомнит другой PID. TDPID - это просто переменная. дальше вставляете свой код. Когда нужно будет tcpdump остановить, просто посылаем ему Ctrl+C kill -3 $TDPID P.S. Важный момент, на который все натыкаются и долго не могут понять, что не так. В строке TDPID=$! не должно быть пробелов. Если написать так TDPID = $!, то работать не будет.Ответ 2
Мне кажется, должно быть более простое решение. совершенно верно. если речь идёт о сетевой подсистеме программы linux версии выше или равной 2.0 (или 2.1? никак не могу запомнить), то можно воспользоваться программой ip: $ ip route get 8.8.8.8 8.8.8.8 via 192.168.0.1 dev eth0 src 192.168.0.2 cache в приведённом примере вывода 192.168.0.2 — это и есть ip-адрес, с которым будут покидать систему пакеты, адресованные к 8.8.8.8. если полный вывод программы не подходит, и этот адрес надо извлечь, то для удобства обработки можно добавить опцию -o (oneline): $ ip -o route get 8.8.8.8 8.8.8.8 via 192.168.0.1 dev eth0 src 192.168.0.2 \ cache и извлечь его с помощью, например, программы sed (кстати, параметры route и get в данном случае можно сократить до одной буквы): $ ip -o r g 8.8.8.8 | sed 's/.*src \([^ ]\+\) .*/\1/' 192.168.0.2 подробности смотрите в документации к программе ip: man ip, man ip-route. кстати, маршрутов может оказаться и более одного (например, при использовании на данной машине динамической маршрутизации). они все будут отображены, и, следовательно, в окончательном выводе будет более одной строчки с ip-адресами.
Комментариев нет:
Отправить комментарий