All of lore.kernel.org
 help / color / mirror / Atom feed
From: tom <tom@t0mb.net>
To: Joris Dobbelsteen <Joris@familiedobbelsteen.nl>
Cc: netfilter@lists.netfilter.org
Subject: Re: Traffic auditing per user
Date: Tue, 12 Dec 2006 23:42:36 +0000	[thread overview]
Message-ID: <457F3E6C.5000606@t0mb.net> (raw)
In-Reply-To: <73427AD314CC364C8DF0FFF9C4D693FF546D@nehemiah.joris2k.local>

Joris Dobbelsteen wrote:
> Thanks Tom,
>
> This seems quite promising. It looks like /proc/net/tcp and
> /proc/net/udp must be combined together with /proc/net/ip_conntrack.
> The first two to figure out the uid, the latter to find the actual
> bytes/packets transferred.
> Some clever matching the results will be good and some post-processing
> will reveil any delta values (for easier computations later on). Thanks
> for the pointers, these seem to be exactly what I needed!
>
>   
I'm useful on the odd occastion ;)  The code won't actually work as is 
btw.  My mail client stripped out all of the tabbing, and python 
enforces indentation, if you want the working code give me a shout, but 
you've probably got enough to go on.

Enjoy!
> I'll give it some testing later on...
>
>
> A slight note: if you have IPv6 enabled, connections are listed in
> tcp6|udp6 too, also IPv4 connections. It contains the same content, but
> with longer addresses. The following is a IPv4 address, see RFC 3513,
> paragraph 2.5.5...
>    2: 0000000000000000FFFF00001F7EA8C0:0016
> 0000000000000000FFFF0000017EA8C0:084E 01 00000034:00000000 01:0000001C
> 00000000     0        0 10047 4 cb314040 80 10 1 3 100
>
> I'm a little bit worried about endianess of linux implementations on
> different hardware platforms, however. Hopefully they did it right:
> correct formation conversion.
>
> - Joris
>
>   
>> -----Original Message-----
>> From: tom [mailto:tom@t0mb.net] 
>> Sent: zondag 10 december 2006 15:52
>> To: Joris Dobbelsteen
>> Cc: netfilter@lists.netfilter.org
>> Subject: Re: Traffic auditing per user
>>
>> /proc/net/tcp and udp both have a column for the UID of any 
>> particular connection. The last column is the inode of the 
>> socket, and you can resolve this to a prticular program by 
>> searching through all the /proc/[0-9]+/fd/ folders. There will 
>> be symbolic links to sockets and one of them will have the 
>> inode. Here's an example from /proc/net/tcp
>>
>> sl local_address rem_address st tx_queue rx_queue tr tm->when 
>> retrnsmt uid timeout inode
>>
>> 7: CAF01B52:CD14 5DC20B55:1A0B 01 00000000:00000000 
>> 02:000855AB 00000000
>> 666 0 11007 2 f6780a00 815 40 30 2 100
>>
>> as you can see, my UID is 666
>>
>>
>> I wrote this code for a netstat plugin for an app i'm working 
>> on. (it's python btw)
>>
>> def get_connections(self):
>>
>> temp_inodes = {}
>> cdict = {}
>>
>> try:
>> procnettcp_f = open('/proc/net/tcp')
>> except IOError:
>> raise
>>
>> procnettcp_f.readline()
>> while 1:
>> cdict = {}
>> line = procnettcp_f.readline()
>> if line == '': break
>> spline = line.split()
>> inode = spline[9]
>> [lhost, lport] = spline[1].split(':', 1) [rhost, rport] = 
>> spline[2].split(':', 1) status = spline[3]
>>
>> if int(status,16) == 0x01:
>> cdict['status'] = "ESTABLISHED"
>> elif int(status,16) == 0x0A:
>> cdict['status'] = "LISTENING"
>> elif int(status, 16) == 0x100:
>> cdict['status'] = "WAITING"
>> else:
>> cdict['status'] = '-'
>> continue
>>
>> lhost = int(lhost, 16)
>> rhost = int(rhost, 16)
>> cdict['lport'] = str(int(lport,16))
>> cdict['rport'] = str(int(rport,16))
>> cdict['lhost'] = ".".join(map(str,(lhost & 0xff, (lhost >> 8) 
>> & 0xff, (lhost >> 16) & 0xff, (lhost >> 24) & 0xff))) 
>> cdict['rhost'] = ".".join(map(str,(rhost & 0xff, (rhost >> 8) 
>> & 0xff, (rhost >> 16) & 0xff, (rhost >> 24) & 0xff))) 
>> temp_inodes[inode] = cdict for iknowd, pid, prog_name in 
>> self.resolve_inodes(temp_inodes):
>> temp_inodes[iknowd]['pid'] = pid
>> temp_inodes[iknowd]['prog_name'] = prog_name print temp_inodes 
>> return temp_inodes
>>
>> def resolve_inodes(self, inodes):
>>
>> for file in glob.glob('/proc/[0-9]*/fd/*'):
>> try:
>> fdno = os.readlink(file)
>> if fdno[0:8] == 'socket:[':
>> this_inode = fdno[8:-1]
>> if this_inode in inodes:
>> pid = file.split('/')[2]
>> try:
>> pid_status = open(''.join(['/proc/', pid, '/status'])) name = 
>> pid_status.readline().split()[-1].rstrip()
>> pid_status.close()
>> except IOError:
>> name = '?'
>> yield this_inode, pid, name
>> except os.error:
>> pass
>>
>>
>> This code doesn't do anything with the UID, but it's there in 
>> /proc/net/tcp, so easy to get to. I don't think netfilter 
>> itself really has what you're looking for. Hope this helps you 
>> out. Another thing worth mentioning actually is 
>> /proc/net/ip_conntrack, which has lines like. This would be 
>> useful in conjunction with the corresponding lines from 
>> /proc/net/tcp etc...
>>
>> tcp 6 431482 ESTABLISHED src=82.27.240.202 dst=213.171.192.50
>> sport=34571 dport=143 packets=274 bytes=15668 src=213.171.192.50
>> dst=82.27.240.202 sport=143 dport=34571 packets=268 
>> bytes=153509 [ASSURED] mark=0 use=1
>>
>> Joris Dobbelsteen wrote:
>>     
>>> I'm looking for a solution to audit network traffic usage per user.
>>> After a long enough search I was not able to find a solution that 
>>> suited my needs.
>>>
>>> It must fit the following requirements:
>>> * The traffic must be logged on a uid basis.
>>> * Some traffic should not be counted, which is protocol 
>>>       
>> (i.e. non-IP) 
>>     
>>> and IP address based (i.e. no local network).
>>> * Of course not have a dramatic effect on performance
>>>
>>> Hopefully its not to hard for me, thus the tool has some (decent) 
>>> instructions/documentation.
>>> Further I want to keep using my stock application. The platform is 
>>> Ubuntu 6.06 LTS, and I prefer to have the packages from the 
>>> repositories, rather than my own complications. Mostly for 
>>>       
>> reasons of 
>>     
>>> testing and maintenance.
>>>
>>> I would guess this is not directly a netfilter question, but 
>>>       
>> it should 
>>     
>>> be close enough.
>>>
>>> - Joris
>>>
>>>   
>>>       
>>     



  reply	other threads:[~2006-12-12 23:42 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-12-12 16:55 Traffic auditing per user Joris Dobbelsteen
2006-12-12 23:42 ` tom [this message]
  -- strict thread matches above, loose matches on Subject: below --
2006-12-03 23:11 Joris Dobbelsteen
2006-12-10 14:52 ` tom

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=457F3E6C.5000606@t0mb.net \
    --to=tom@t0mb.net \
    --cc=Joris@familiedobbelsteen.nl \
    --cc=netfilter@lists.netfilter.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.