See socket options on existing sockets created by other apps?

6.6k views Asked by At

I'd like to test whether particular socket options have been set on an existing socket. Ie, pretty much everything you can see in:

#!/usr/bin/env python
'''See possible TCP socket options'''

import socket

sockettypelist = [x for x in dir(socket) if x.startswith('SO_')]
sockettypelist.sort()
for sockettype in sockettypelist:
    print sockettype

Anyone know how I can see the options on existing sockets, ie those created by other processes? Alas nearly all the documentation I read on Python socket programming is about making new sockets.

3

There are 3 answers

1
Cajga On BEST ANSWER

Unfortunately, nailer's answer only catches the SOL_TCP level socket options and does not the SOL_SOCKET level ones (like SO_KEEPALIVE).

Some of the distributions ships some examples together with systemtap. One of them is pfiles.stp that you can use to get the socket options from the sockets of a running process. Example from the file:

$ ./pfiles.stp `pgrep udevd`
   787: udevd
  Current rlimit: 32 file descriptors
   0: S_IFCHR mode:0666 dev:0,15 ino:396 uid:0 gid:0 rdev:1,3
      O_RDWR|O_LARGEFILE 
      /dev/null
   1: S_IFCHR mode:0666 dev:0,15 ino:396 uid:0 gid:0 rdev:1,3
      O_RDWR|O_LARGEFILE 
      /dev/null
   2: S_IFCHR mode:0666 dev:0,15 ino:396 uid:0 gid:0 rdev:1,3
      O_RDWR|O_LARGEFILE 
      /dev/null
   3: S_IFDIR mode:0600 dev:0,9 ino:1 uid:0 gid:0 rdev:0,0
      O_RDONLY 
      inotify
   4: S_IFSOCK mode:0777 dev:0,4 ino:2353 uid:0 gid:0 rdev:0,0
      O_RDWR 
      socket:[2353]
      SO_PASSCRED,SO_TYPE(2),SO_SNDBUF(111616),SO_RCVBUF(111616)
        sockname: AF_UNIX
   5: S_IFSOCK mode:0777 dev:0,4 ino:2354 uid:0 gid:0 rdev:0,0
      O_RDWR 
      socket:[2354]
      SO_TYPE(2),SO_SNDBUF(111616),SO_RCVBUF(33554432)
        ulocks: rcv
   6: S_IFIFO mode:0600 dev:0,6 ino:2355 uid:0 gid:0 rdev:0,0
      O_RDONLY|O_NONBLOCK 
      pipe:[2355]
   7: S_IFIFO mode:0600 dev:0,6 ino:2355 uid:0 gid:0 rdev:0,0
      O_WRONLY|O_NONBLOCK 
      pipe:[2355]
0
mikemaccana On

This is not possible in Python.

The Linux kernel does not provide a mechanism in /procfs to report on TCP socket states (unlike BSD and other Unix-like OSs). As the kernel doesn't expose this info, we can't see it via the python-linux-procfs module or similar.

See lsof FAQ item 3.14.1:

Q. ‘Why doesn't lsof report socket options, socket states, and TCP flags and values for my dialect?’.

A. 'socket options, socket states, and TCP flags and values are not available via the /proc file system.'

However SystemTap's Network tapset provides a tcp.setsockopt breakpoint which can be used to intercept socket options set by a process, however this would be handled in stap rather than python.

I created the required tapset as follows:

# Show sockets setting options

# Return enabled or disabled based on value of optval
function getstatus(optlen)
{
    if ( optlen == 1 )
        return "enabling"
    else
        return "disabling"
}

probe begin
{
    print ("\nChecking for apps making socket calls\n")
}

# See apps setting a socket option 
probe tcp.setsockopt
{
    status = getstatus(user_int($optval))
    printf ("  App '%s' (PID %d) is %s socket option %s... ", execname(), pid(), status, optstr)
}

# Check setting the socket option worked
probe tcp.setsockopt.return
{
    if ( ret == 0 )
        printf ("success")
    else
        printf ("failed")
    printf ("\n")    
}


probe end
{
    print ("\nClosing down\n")
}
1
Adrien Plisson On

the socket library is indeed to create new sockets and manipulate them. sockets created in other processes are not visible for obvious security reasons: you would not want any random application changing the way you manage your own socket, or worse reading data from your socket before you. so sockets are system objects, referenced by a handle, with (on a decent OS) access rights applying to them. that's why you can't list existing sockets created by other processes.

eventually, you may find a way to retrieve socket handles (there should be a way somewhere, i remember seeing a way to list system handles on Windows), but this would still be very specific to your OS, so likely not available in python, and you may still not have the right to perform anything on those sockets.

now, if you are only curious to know how a specific application achieved a specific feature, there are other ways: the most obvious is installing a proxy or a firewall (i remember that my Kerio WinRoute Firewall listed socket options), or just asking stackoverflow about how to achieve this feat.