간단히 말해서:tcpdump
UART를 통해 원격 출력을 로컬로 올바르게 전송하는 방법은 무엇입니까 wireshark
?
임베디드 장치를 통해 흐르는 패킷을 캡처하려고 하는데 장치에 아무것도 설치할 수 없습니다. 다행히 직렬 포트에서 getty가 열리고 tcpdump가 설치되었습니다. 불행하게도 SSH, dumpcap, tshark는 없습니다.
스트레이트 튜브형
먼저 tty를 구성하고 데이터를 와이어샤크로 연결해 보았습니다.
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가 여전히 일부 특수 문자(예: 줄 바꿈 또는 캐리지 리턴)를 변환하고 있기 때문이라고 생각합니다.
멍청해지기: PySerial을 통한 16진수 덤프
그래서 나는 이것이 형편없다는 것을 알고 있지만 다른 아이디어가 없었기 때문에 이것이 내가 생각해낸 것입니다:
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)라는 문제를 표시합니다. 녹음이 중지됩니다.
도와주세요! :)
tcpdump 옵션을 사용해 보았지만 -s
적은 양으로도 작동하지 않는다는 것을 알 수 있습니다.
나는 또한 picocom의 파이프를 시도했지만 아무 소용이 없었습니다.
따라서 아이디어가 있거나 작동할 수 있는 UART 터널링 소프트웨어가 있거나 stty의 (무능한) 사용에 대한 의견이 있거나 Python 스크립트에 대한 개선 사항이 있으면 매우 기쁠 것입니다!
Wireshark는 2.2.5, tcpdump는 4.5.0, libpcap은 1.5.0입니다.
답변1
드디어 실제로 작동하게 되었습니다. 완벽한 설정은 아니지만 적어도 작동하므로 나중에 누군가에게 도움이 될 수 있습니다.
위의 Python 스크립트를 사용했습니다.py 직렬 포트UART를 통해 tcpdump를 시작하고 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))