1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#!/usr/bin/env python3
# Capture from a remote server over SSH which has dumpcap.
#
# After copying this file to the extcap folder (see Help -> About
# for location), you can capture with:
#
# wireshark -i ssh-dumpcap -k \
# -oextcap.ssh_dumpcap.remotehost:user@host \
# -oextcap.ssh_dumpcap.remoteinterface:nflog:0x1234
#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-version')
parser.add_argument('--extcap-interface', metavar='IFACE')
parser.add_argument('--extcap-capture-filter', metavar='CFILTER')
parser.add_argument('--fifo', metavar='FIFO')
parser.add_argument('--remote-host', metavar='HOST')
parser.add_argument('--remote-interface', metavar='IFACE')
def extcap_interfaces():
print("extcap {version=1.0}")
print("interface {value=ssh-dumpcap}{display=Remote dumpcap}")
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}")
def extcap_config(iface):
print("""
arg {number=0}{call=--remote-host}{display=Remote SSH server address}{type=string}{tooltip=The remote SSH host. It can be both an IP address or a hostname}{required=true}{group=Server}
arg {number=1}{call=--remote-interface}{display=Remote interface}{type=string}{tooltip=The remote network interface used for capture}{group=Capture}
""".strip())
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, ssh_host, cfilter, outfile):
tcpdump_args = [
"dumpcap",
"-i", iface,
"-p",
"-q",
"-w", "-",
]
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')
#if args.extcap_interface != "ssh-dumpcap":
# parser.error('only ssh-dumpcap is supported as interface name')
iface = args.remote_interface
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.remote_host, 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)
|