summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2016-09-24 11:22:47 +0200
committerPeter Wu <peter@lekensteyn.nl>2016-09-24 11:22:47 +0200
commit6951d901827e9d31a8c09a3a30d6d65ac25514c7 (patch)
treec575480d6e2cafb83f06b52c35de5d38e88cedf1
parent21651a6e4c8ac21b1989c5847c04e96fd6c8b333 (diff)
downloadwireshark-notes-6951d901827e9d31a8c09a3a30d6d65ac25514c7.tar.gz
extcap/ssh-tcpdump: example remote tcpdump
Requires Python 3.4, but it can be adapted for older versions. It demonstrates how "easy" it is to capture remotely over SSH when only tcpdump is installed without dumpcap (in that case you could use sshdump). Note that on stopping/restarting captures, you still get some stderr messages ("Dropped privileges", but that can be ignored). See also https://ask.wireshark.org/questions/55768/remote-interface-linux
-rwxr-xr-xextcap/ssh-tcpdump124
1 files changed, 124 insertions, 0 deletions
diff --git a/extcap/ssh-tcpdump b/extcap/ssh-tcpdump
new file mode 100755
index 0000000..02fcca6
--- /dev/null
+++ b/extcap/ssh-tcpdump
@@ -0,0 +1,124 @@
+#!/usr/bin/env python3
+# Capture from a remote server over SSH which has tcpdump but no dumpcap.
+#
+# After copying this file to the extcap folder (see Help -> About
+# for location), you can use the name "ssh-tcpdump:" followed by the interface
+# name:
+#
+# SSHHOST=peterw@someserver wireshark -i ssh-tcpdump:eth0 -p -k
+#
+# Note: interface names are currently hard-coded (lo and eth0).
+
+#from __future__ import print_function
+
+import argparse, os, sys
+from shlex import quote
+from signal import SIGINT
+
+parser = argparse.ArgumentParser()
+
+# Actions
+parser.add_argument('--extcap-interfaces', action='store_true')
+parser.add_argument('--extcap-dlts', action='store_true')
+parser.add_argument('--extcap-config', action='store_true')
+parser.add_argument('--capture', action='store_true')
+
+parser.add_argument('--extcap-interface', metavar='IFACE')
+
+parser.add_argument('--extcap-capture-filter', metavar='CFILTER')
+parser.add_argument('--fifo', metavar='FIFO')
+
+IFACE_PREFIX = 'ssh-tcpdump:'
+# TODO currently hard-coded interfaces, maybe add preferences?
+ifaces = [
+ 'lo',
+ 'eth0',
+]
+
+def extcap_interfaces():
+ print("extcap {version=1.0}")
+ for iface in ifaces:
+ print("interface {value=%s%s}{display=Remote tcpdump: %s}" % (
+ IFACE_PREFIX, iface, iface
+ ))
+
+def extcap_dlts(iface):
+ # Required for the interface to show up in the interace
+ print("dlt {number=147}{name=USER0}{display=Remote capture dependent DLT}")
+
+# TODO consider configuration option for setting the SSH host?
+def extcap_config(iface):
+ pass
+
+def redirect_stdout(outfile):
+ STDOUT_FILENO = 1
+ try: os.close(STDOUT_FILENO)
+ except OSError: pass
+ fd = os.open(outfile, os.O_WRONLY, 0o600)
+ # TODO this requires Py 3.4, maybe old version can use dup2
+ os.set_inheritable(fd, True)
+ if fd != STDOUT_FILENO:
+ os.dup2(fd, STDOUT_FILENO)
+ os.close(fd)
+
+def extcap_capture(iface, cfilter, outfile):
+ ssh_host = os.getenv("SSHHOST")
+ if not ssh_host:
+ raise RuntimeError("Missing SSHHOST")
+ ssh_user = os.getenv('SSHUSER')
+ if not ssh_user:
+ if '@' in ssh_host:
+ ssh_user = ssh_host.split('@')[0]
+ else:
+ ssh_user = os.getenv('USER')
+ tcpdump_args = [
+ "sudo",
+ "tcpdump",
+ "-i", iface,
+ "-p",
+ "-U",
+ "-w", "-",
+ ]
+ # Change to a less-privileged user
+ if ssh_user:
+ tcpdump_args += ["-Z", ssh_user]
+ if cfilter:
+ tcpdump_args += [cfilter]
+ args = [
+ "ssh", ssh_host,
+ " ".join(quote(c) for c in tcpdump_args),
+ ]
+ #import subprocess; subprocess.call(["ls", "-l", "/proc/%d/fd/" % os.getpid()], stdout=2)
+ redirect_stdout(outfile)
+ os.execvp(args[0], args)
+
+def main():
+ args = parser.parse_args()
+ if args.extcap_interfaces:
+ return extcap_interfaces()
+
+ if not args.extcap_interface:
+ parser.error('Missing --extcap-interface option')
+
+ iface = args.extcap_interface[len(IFACE_PREFIX):]
+
+ if args.extcap_dlts:
+ return extcap_dlts(iface)
+ elif args.extcap_config:
+ return extcap_config(iface)
+ elif args.capture:
+ if not args.fifo:
+ parser.error('Missing --fifo option for --capture')
+ return extcap_capture(iface, args.extcap_capture_filter, args.fifo)
+ else:
+ parser.error('Missing action')
+ return 1
+
+if __name__ == '__main__':
+ try:
+ sys.exit(main())
+ except KeyboardInterrupt:
+ sys.exit(128 + SIGINT)
+ except OSError as e:
+ print(e, file=sys.stderr)
+ sys.exit(1)