Skip to content

Instantly share code, notes, and snippets.

@hleroy
Created May 30, 2020 16:31
Show Gist options
  • Save hleroy/9fd589a243a978caa001c8b58ee6a6ca to your computer and use it in GitHub Desktop.
Save hleroy/9fd589a243a978caa001c8b58ee6a6ca to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''
check_mtu.py -- Check link MTU by sending UDP packets with increasing payload size
positional arguments:
host host to send packet to. If omitted, defaults to
www.google.com
optional arguments:
-h, --help show this help message and exit
-p PORT, --port PORT port to send packet to. If omitted, defaults to 80
-l PAYLOADS, --payloads PAYLOADS
range of payloads to test. If omitted, defaults to
1420-1480
-v, --verbose print the result of each test
@author: Hervé Le Roy
@contact: hleroy@hleroy.com
'''
import socket
from argparse import ArgumentParser
def payload_range(string):
val_list = string.split('-')
return range(int(val_list[0]), int(val_list[1]) + 1)
def main():
"Check link MTU by sending UDP packets with increasing payload size"
# Defaults
DEFAULT_HOST = "www.google.com"
DEFAULT_PORT = 80
DEFAULT_PAYLOADS = "1420-1480"
# Setup argument parser
parser = ArgumentParser(
description="Check link MTU by sending UDP packets with increasing payload size")
parser.add_argument("host", nargs="?", default=DEFAULT_HOST,
help="host to send packet to. If omitted, defaults to www.google.com")
parser.add_argument("-p", "--port", type=int, default=DEFAULT_PORT,
help="port to send packet to. If omitted, defaults to 80")
parser.add_argument('-l', '--payloads', type=payload_range, default=DEFAULT_PAYLOADS,
help="range of payloads to test. If omitted, defaults to 1420-1480")
parser.add_argument('-v', '--verbose', action='store_true',
help="print the result of each test")
args = parser.parse_args()
# Initialize max payloads
max_payload = 0
# Open socket
IP_MTU_DISCOVER = 10 # MTU discover
IP_PMTUDISC_DO = 2 # Always set DF (don't fragment) bit
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for payload in args.payloads:
s.connect((args.host, args.port))
s.setsockopt(socket.IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DO)
try:
s.send(b'#' * payload)
except socket.error:
if args.verbose:
print('Failed to sent UDP packet with a payload of {} bytes'.format(
payload))
else:
max_payload = payload
if args.verbose:
print('Succesfully sent UDP packet with a payload of {} bytes'.format(
payload))
if max_payload == 0:
print('No packet went through. Try decreasing payload size.')
exit()
if max_payload == args.payloads[-1]:
print('All packets went through. Try increasing payload size.')
exit()
# MTU = max_payload + 20 (IP header) + 8 (UDP header)
print('Path MTU to {} is {}'.format(args.host, max_payload + 28))
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment