用Python捕获Mininet中两台主机的流量



我目前有两台运行客户端和服务器端Python程序的主机,它们相互发送TLS流量-我已经在mininet之外测试了它以确认它有效(并且它确实有效!)

然而,这里的目标是使用tcpdump/tshark wireshark捕捉这两个主机之间的TLS交通。我已经尝试过诸如使用quietRunsubprocess.Popen来调用tcpdump -i any -w capture.pcap之类的事情,但是这些似乎并没有捕获我的主机的流量,或者它们会停滞,直到我ctrl+c和/或直接进入CLI(net)。

供参考;这些都是使用mininet CLI -目的是通过编程来完成的。

下面是当前代码:

#!/usr/bin/python
# -*- coding: utf-8 -*-
# from sys import exit  # pylint: disable=redefined-builtin
import sys
import os
import subprocess
import time
from functools import partial
from mininet.node import Host, UserSwitch, OVSKernelSwitch, Controller, Switch
from mininet.topo import Topo, SingleSwitchTopo
from mininet.util import quietRun, pmonitor
from mininet.log import error, lg, info, setLogLevel
from mininet.net import Mininet
from mininet.cli import CLI
from mininet.link import TCLink

class ExperimentTopology(Topo):
"""Custom mininet topology for robot-controller experiments"""
def __init__(self):
"""Create custom topology"""
# Initialize topology
Topo.__init__(self)
# Add hosts and switches
switch = self.addSwitch("s1")
h1= self.addHost("h1")
h2= self.addHost("h2")
# Set link parameters (delay, etc.)
# bw = Bandwidth in Mbps
# delay = Link delay (s, ms, us)
# loss = Percentage packet loss
# max_queue_size = Maximum queue size
# use_htb = Use the Hierarchical Token Bucket rate limiter and netem delay/loss emulator?
# linkopts = dict(bw=10, delay="5ms", loss=10) #max_queue_size=1000
# Add links
self.addLink(switch, h1)  # to use params, add ", **linkopts"
self.addLink(switch, h2)

def main():
lg.setLogLevel("info")
# quietRun('tcpdump -i any -w capture.pcap')
net = Mininet(topo=ExperimentTopology(), waitConnected=True)
net.start()
h1= net.get('h1')
h1p= robot.popen('python3 tls_server.py -i %s -p %d &' % (str(h1.IP()), 443))
# time.sleep(10)
h2 = net.get('h2')
h2.cmd('python3 tls_client.py -i %s -p %d -m %s -d %s -s %s' % (str(h2.IP()), 443, 'x', 1, '12.5'))
# net.popen('tcpdump -i any -w capture.pcap') # _process = subprocess.Popen(['sudo', 'tcpdump', '-i', 'any', '-w', 'capture.pcap'])
s1 = net.get('s1')
s1.cmd(os.system('sudo tshark -w $HOME/captures/capture.pcap'))
CLI(net)
h1p.terminate()
net.stop()
# _process.terminate()
if __name__ == '__main__':
main()

**编辑:TLS客户端和服务器文件::**

tls_client.py:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import socket
import ssl
import optparse
import time
from scapy.all import *
load_layer("usb")
parser = optparse.OptionParser()
parser.add_option('-i', dest='ip', default='127.0.0.1')
parser.add_option('-p', dest='port', type='int', default=12345)
parser.add_option('-m', dest='movement', default='x')
parser.add_option('-d', dest='distance', type='int', default=1)
parser.add_option('-s', dest='speed', default='12.5')
(options, args) = parser.parse_args()
hostname = options.ip  # '127.0.0.1'
port = options.port  # 443
context = ssl.SSLContext()
# Confirm these min + max values
MIN_X = 150
MAX_X = 300
MIN_Y = -230
MAX_Y = 230
MIN_Z = -50
MAX_Z = 150
MIN_SPEED = 12.5 # 12.5, 25, 50, 100
MAX_SPEED = 100.0
NUM_RUNS = 5
with socket.create_connection((hostname, port)) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
print(ssock.version())
# Load pcap file
# x_packets = rdpcap('pcaps/operation_move_x.pcapng')
# Now we have handshake and socket open, lets send messages
# Get data from wireshark dump, and use ssock.sendall(bytes)
# TODO: Set these (x,y,z) to the default starting values for robot
i = 0
g = 0
x = 0.00
y = 0.00
z = 0.00
f = options.speed # 12.5
if options.movement == 'x':
for j in range(NUM_RUNS):
i = 0
for k in [k for k in range(MIN_X, MAX_X+1, int(options.distance))]:
x = k
payload = '#' + str(i) + ' G' + str(g) + ' X' + str(x) + ' Y' + str(y) + ' Z' + str(z) + ' F' + str(f)
ssock.sendall(bytes(payload, encoding='utf-8'))
time.sleep(1)
i += 1
elif options.movement == 'y':
for j in range(NUM_RUNS):
i = 0
for k in [k for k in range(MIN_X, MAX_X+1, int(options.distance))]:
y = k
payload = '#' + str(i) + ' G' + str(g) + ' X' + str(x) + ' Y' + str(y) + ' Z' + str(z) + ' F' + str(f)
ssock.sendall(bytes(payload, encoding='utf-8'))
time.sleep(1)
i += 1
elif options.movement == 'z':
for j in range(NUM_RUNS):
i = 0
for k in [k for k in range(MIN_X, MAX_X+1, int(options.distance))]:
z = k
payload = '#' + str(i) + ' G' + str(g) + ' X' + str(x) + ' Y' + str(y) + ' Z' + str(z) + ' F' + str(f)
ssock.sendall(bytes(payload, encoding='utf-8'))
time.sleep(1)
i += 1
elif options.movement == 'xy':
for i in range(NUM_RUNS):
i = 0
for k in [k for k in range(MIN_X, MAX_X+1, int(options.distance))]: # y pos will be x-120 (too keep in Y range)
x = k
y = k-120
payload = '#' + str(i) + ' G' + str(g) + ' X' + str(x) + ' Y' + str(y) + ' Z' + str(z) + ' F' + str(f)
ssock.sendall(bytes(payload, encoding='utf-8'))
time.sleep(1)
i += 1
elif options.movement == 'xz':
for i in range(NUM_RUNS):
i = 0
z = 0
for k in [k for k in range(MIN_X, MAX_X+1, int(options.distance))]: # z pos will be (x/10)+5 (too keep in Z range)
x = k
if z == MAX_Z:
z = MAX_Z
else:
z += 1
payload = '#' + str(i) + ' G' + str(g) + ' X' + str(x) + ' Y' + str(y) + ' Z' + str(z) + ' F' + str(f)
ssock.sendall(bytes(payload, encoding='utf-8'))
time.sleep(1)
i += 1
elif options.movement == 'yz':
for i in range(NUM_RUNS):
i = 0
z = 0
for k in [k for k in range(MIN_Y, MAX_Y+1, int(options.distance))]:
y = k
if z >= MAX_Z:
z = 0
else:
z += 1
payload = '#' + str(i) + ' G' + str(g) + ' X' + str(x) + ' Y' + str(y) + ' Z' + str(z) + ' F' + str(f)
ssock.sendall(bytes(payload, encoding='utf-8'))
time.sleep(1)
i += 1
elif options.movement == 'xyz':
for i in range(NUM_RUNS):
i = 0
y = MIN_Y
z = MIN_Z
for k in [k for k in range(MIN_X, MAX_X+1)]:
x = k
if y >= MAX_Y:
y = 0
else:
y += 1
if z >= MAX_Z:
z = 0
else:
z += 1
payload = '#' + str(i) + ' G' + str(g) + ' X' + str(x) + ' Y' + str(y) + ' Z' + str(z) + ' F' + str(f)
ssock.sendall(bytes(payload, encoding='utf-8'))
time.sleep(1)
i += 1

** tls_server.py **

#!/usr/bin/python
# -*- coding: utf-8 -*-
import socket
import ssl
import optparse
parser = optparse.OptionParser()
parser.add_option('-i', dest='ip', default='')
parser.add_option('-p', dest='port', type='int', default=12345)
(options, args) = parser.parse_args()
hostname = options.ip  # '127.0.0.1'
port = options.port  # 443
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain('robot.cert', 'robot.key')
print('Loaded certificate and key..')
with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock:
print('Socket starting..')
sock.bind((hostname, port))
sock.listen(25)
with context.wrap_socket(sock, server_side=True) as ssock:
print('Socket connection established!')
(conn, addr) = ssock.accept()
f = open('server_output.txt', 'w')
while True:
message = conn.recv()
if not message:
break
# message = message.decode()
f.write('%s: %sn' % (addr, message))
f.flush()
# print(message)

我在过去通过使用节点的popen方法来启动pcap,然后终止来关闭进程并强制它记录pcap。

假设你有一个节点叫做h1. 然后你可以输入

h1_pcap = h1.popen('tcpdump -w h1_dump.pcap')
# Do stuff here
# ...
h1_pcap.terminate()

这会将h1上的所有流量记录到h1_dump中。pcap一旦脚本执行。

最新更新