Skip to content

Instantly share code, notes, and snippets.

@Mithrilwoodrat
Created February 26, 2019 15:50
Show Gist options
  • Save Mithrilwoodrat/e5d822bbb15e24ff41c422470289dc5d to your computer and use it in GitHub Desktop.
Save Mithrilwoodrat/e5d822bbb15e24ff41c422470289dc5d to your computer and use it in GitHub Desktop.
Linux netstat in python
# -*- coding: utf-8 -*-
# ref
# * https://gist.github.com/aleiphoenix/0e886336522c2f41412d
# * https://stackoverflow.com/questions/3319521/how-can-i-match-each-proc-net-tcp-entry-to-each-opened-socket
# * https://stackoverflow.com/questions/14667215/finding-a-process-id-given-a-socket-and-inode-in-python-3
# read /proc/net/tcp get address port and inode. get pid by checking every sysbol link to this inode in every /proc/<PID>/fd
import re
import os
import sys
with open('/proc/net/tcp') as f:
lineno = 0
sockets = []
for line in f:
lineno += 1
if lineno == 1:
continue
sockets.append(line.strip())
columns = ("seq", "uid", "inode", "local", "remote", "timeout")
title = dict()
for c in columns:
title[c] = c
def split_every_n(data, n):
return [data[i:i+n] for i in range(0, len(data), n)]
def convert_linux_netaddr(address):
hex_addr, hex_port = address.split(':')
addr_list = split_every_n(hex_addr, 2)
addr_list.reverse()
addr = ".".join(map(lambda x: str(int(x, 16)), addr_list))
port = str(int(hex_port, 16))
return "{}:{}".format(addr, port)
def format_line(data):
#print data
return ("{seq:4s} {uid:5s} {local:25s} {remote:25s} " +
"{timeout:8s} {inode:8s} \n".format(**data))
def find_pid(inode):
# get a list of all files and directories in /proc
procFiles = os.listdir("/proc/")
# remove the pid of the current python process
procFiles.remove(str(os.getpid()))
# set up a list object to store valid pids
pids = []
for f in procFiles:
try:
# convert the filename to an integer and back, saving the result to a list
integer = int(f)
pids.append(str(integer))
except ValueError:
# if the filename doesn't convert to an integer, it's not a pid, and we don't care about it
pass
for pid in pids:
# check the fd directory for socket information
fds = os.listdir("/proc/%s/fd/" % pid)
for fd in fds:
# save the pid for sockets matching our inode
if ('socket:[%s]' % inode) == os.readlink("/proc/%s/fd/%s" % (pid, fd)):
return pid
rv = []
for info in sockets:
_ = re.split(r'\s+', info)
_tmp = {
'seq': _[0],
'local': convert_linux_netaddr(_[1]),
'remote': convert_linux_netaddr(_[2]),
'uid': _[7],
'timeout': _[8],
'inode': _[9],
'pid': find_pid(_[9])
}
rv.append(_tmp)
if len(rv) > 0:
title = "{:4s} {:5s} {:25s} {:25s} {:8s} {:8s} \n".format(*title)
sys.stderr.write(title)
for _ in rv:
sys.stdout.write(str(_)+'\n')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment