TL;DR:Как правильно передать вывод удаленного устройства tcpdump
на локальный компьютер через UART wireshark
?
Я пытаюсь перехватить пакеты, которые проходят через встроенное устройство, на которое у меня нет возможности что-либо установить. К счастью, на последовательном интерфейсе открыт getty и установлен tcpdump. К сожалению, нет SSH, нет dumpcap, нет tshark.
Прямая труба
Сначала я попытался настроить tty и передать данные в Wireshark через каналы.
stty -F /dev/ttyUSB0 raw
stty -F /dev/ttyUSB0 -echo -echoe -echok
cat /dev/ttyUSB0 | wireshark -k -i -
# On another terminal:
echo "tcpdump -U -s0 -i eth0 -w - 2>/dev/null" > /dev/ttyUSB0
Wireshark жалуется, что входные данные не соответствуют формату libpcap, поскольку команда возвращается обратно, и мне не удалось от этого избавиться.
Использование сырого PySerial
Поэтому я решил создать скрипт на Python, который будет контролировать работу конвейера:
import serial
import sys
import subprocess
import fcntl
def main(args):
with serial.Serial('/dev/ttyUSB0', 115200, timeout=0) as ser:
length = ser.write(b"tcpdump -U -s0 -i eth0 -w - 2> /dev/null\n") + 1
# Discard the echoed command line
while length > 0:
discard = ser.read(length)
length -= len(discard)
# Spawn wireshark
wireshark = subprocess.Popen(
["wireshark", "-k", "-i", "-"], stdin=subprocess.PIPE
)
# Pipe data from serial to wireshark's input
while True:
data = ser.read(256)
wireshark.stdin.write(data)
try:
wireshark.stdin.flush()
except BrokenPipeError as e:
break
if len(data) > 0: print(data)
# Send "Ctrl+C" to tcpdump
ser.write(b"\x03")
wireshark.wait()
return 0
if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))
Оставив в стороне некоторые проблемы с тем, как скрипт должен правильно заканчиваться, это не сработало так хорошо, как я себе представлял. Wireshark некоторое время был счастлив, но довольно скоро ввод был испорчен, и запись остановилась. Я думаю, это потому, что tty на хосте все еще преобразует некоторые специальные символы, возможно, перевод строки или возврат каретки.
Становлюсь глупым: hexdump через PySerial
Я знаю, что это глупо, но поскольку у меня не было других идей, вот что я придумал:
import serial
import sys
import subprocess
import binascii
def main(args):
with serial.Serial('/dev/ttyUSB0', 115200, timeout=5) as ser:
# Spawn tcpdump on the host and convert the raw output to stupid hex format
# We need hexdump -C because that's the only format that doesn't mess up with the endianess
length = ser.write(b"tcpdump -U -s256 -i eth0 -w - 2> /dev/null | hexdump -C\n")
# Discard command line that is echoed
discard = ser.readline()
# Spawn wireshark
wireshark = subprocess.Popen(
["wireshark", "-k", "-i", "-"], stdin=subprocess.PIPE
)
while True:
# Process each line separately
data = ser.readline().decode('ascii')
elements = data.split()
# Remove the address and ascii convertion of hexdump and spaces
hexa = "".join(elements[1:17])
# Convert back hex to binary
real_data = binascii.unhexlify(hexa)
# Feed to the shark
wireshark.stdin.write(real_data)
try:
wireshark.stdin.flush()
except BrokenPipeError as e:
break
# Stop tcpdump
ser.write(b"\x03")
wireshark.wait()
return 0
if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))
Увы, хотя это и работает немного дольше, чем предыдущая версия, когда кадры слишком велики, Wireshark выдает ошибку, сообщающую, что кадр слишком большой, а его длина действительно смехотворна (вроде -1562980309832), и запись снова останавливается.
Пожалуйста помоги! :)
Вы можете заметить, что я пробовал поиграться с -s
опцией tcpdump, но она не сработала даже с небольшими объемами.
Я также пробовал подключаться через picocom, но безрезультатно.
Так что, если у вас есть какие-либо идеи, какое-либо программное обеспечение для туннелирования UART, которое могло бы работать, любые замечания по моему (некомпетентному) использованию stty или любые улучшения моих скриптов на Python, я буду очень рад!
Wireshark — 2.2.5, tcpdump — 4.5.0 с libpcap 1.5.0.
решение1
Наконец-то я заставил это работать. Это не идеальная настройка, но, по крайней мере, она работает, так что, возможно, она поможет кому-то в будущем.
Я использовал скрипт Python поверхPySerialзапустить tcpdump через UART и использовать hexdump, чтобы двоичные данные могли проходить по ссылке без изменения правил транскрипции tty. Затем скрипт Python преобразует данные обратно и передает их в wireshark. Ниже приведен результат, по сравнению с тем, что был в вопросе, я добавил опцию -v
в hexdump, чтобы он не пытался сжимать одинаковые строки.
import serial
import sys
import subprocess
import binascii
def main(args):
with serial.Serial('/dev/ttyUSB0', 115200, timeout=5) as ser:
# Spawn tcpdump on the host and convert the raw output to stupid hex format
# We need hexdump -C because that's the only format that doesn't mess up with the endianess
length = ser.write(b"tcpdump -U -s256 -i eth0 -w - 2> /dev/null | hexdump -Cv\n")
# Discard command line that is echoed
discard = ser.readline()
# Spawn wireshark
wireshark = subprocess.Popen(
["wireshark", "-k", "-i", "-"], stdin=subprocess.PIPE
)
while True:
# Process each line separately
data = ser.readline().decode('ascii')
elements = data.split()
# Remove the address and ascii convertion of hexdump and spaces
hexa = "".join(elements[1:17])
# Convert back hex to binary
real_data = binascii.unhexlify(hexa)
# Feed to the shark
wireshark.stdin.write(real_data)
try:
wireshark.stdin.flush()
except BrokenPipeError as e:
break
# Stop tcpdump
ser.write(b"\x03")
wireshark.wait()
return 0
if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))