Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I am running pptpd on a Centos 5 machine but I didnt set up any logging.

In case of an abuse, I need to determine which of my users did the bad things, meaning I need to log all the traffic. I may have up to 20 users which will use the VPN connection at least 3 hours per day.

Is tcpdump a solution ?

share|improve this question
add comment

2 Answers 2

I have no experience with pptpd, but I do have pptp running on a CentOS machine which acts as a client connecting outward to a DrayTek router.

So, I would imagine, that for each connected user, there will be a corresponding ppp network interface created on the server to service that user. You could setup some iptables rules which log all packets from these ppp interfaces. The the final thing you have to correlate (log) from pptpd is the times when specific users were assigned particular IP addresses. This would then allow you to log the traffic and link it to the corresponding VPN user (even easier if you force VPN users to be assigned a static IP).

You would need to make sure you apply the logging rules in each direction, on the FORWARD chain most likely (to record traffic destined to other hosts on the VPN network, that is routed by the VPN server). Add INPUT and OUTPUT chains if you want to include logging for the server itself (the + denotes all ppp interfaces):

iptables -A FORWARD -i ppp+ -j LOG
iptables -A FORWARD -o ppp+ -j LOG

And obviously, you can tailor the above iptables rules to be more protocol specific, if you are wishing to monitor particular types of traffic.

Using tcpdump to capture PCAPs on a per interface basis would prove a nightmare to implement. You would need to invent some radical way of having a tcpdump process fork and die for each ppp interface that is created and deleted, as users log in and log off. I cannot think of a nice way to do that, and it seems a bit of an overkill anyway to be trying to log the packet contents across each session. Better to have further security measures on the devices they may possibly be connecting to on the private network itself.

share|improve this answer
add comment

I had to implement something similar, but only to the level of logging bandwidth per hour. What I did was set static IPs in chap-secrets for each incoming connection, then added some rules to iptables to count the data.

iptables -N vpn2fw
iptables -N fw2vpn
iptables -A INPUT  -i ppp+ -j vpn2fw
iptables -A OUTPUT -o ppp+ -j fw2vpn

iptables -A vpn2fw -s 10.0.0.100/32
iptables -A fw2vpn -d 10.0.0.100/32

Note that these rules are abstracted from my shorewall configuration and may not be exactly correct.

Obviously changing 10.0.0.100 to the IP of the user's PPTP session. Then I wrote the following script which is run by a cronjob every minute (note, needs gawk):

#!/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin

function getUsage {
        local PARSE=""
        while [ $# -ne 0 ]; do
                PARSE="$PARSE$(iptables -nvx -L $1 && iptables -Z $1)"
                shift;
        done

        echo "$PARSE" | gawk '
        {
                        if ($7 ~ /10\.0\.0\.1\d*/) user=$7
                else    if ($8 ~ /10\.0\.0\.1\d*/) user=$8
                else    next;

                out[user] += $2
        } END {
                for(user in out)
                        printf("%s %d\n", user, out[user]);
        }'
}

function getUser {
        cat /etc/ppp/chap-secrets | awk '{if ($4 == "'$1'") print $1}'
}

function logUsage {
        local DATE="$1"
        local TYPE="$2"
        local DATA="$3"
        local IFS=$'\n'

        if [ "$TYPE" == "RX" ]; then
                local QUERY="INSERT INTO vpn_usage (user, date, rx) VALUES ('%s', '%s', %d) ON DUPLICATE KEY UPDATE rx=rx+VALUES(rx)"
        else
                local QUERY="INSERT INTO vpn_usage (user, date, tx) VALUES ('%s', '%s', %d) ON DUPLICATE KEY UPDATE tx=tx+VALUES(tx)"
        fi

        for LINE in $DATA; do
                USER=$(getUser $(echo $LINE | cut -d' ' -f1))
                test -z "$USER" && continue;
                printf "$QUERY\n" "$USER" "$DATE" "$(echo $LINE | cut -d' ' -f2)" | mysql -u root bandwidth
        done
}

DATE="$(date '+%Y-%m-%d %H:00:00')"
TX="$(getUsage vpn2fw)"
RX="$(getUsage fw2vpn)"
logUsage "$DATE" "TX" "$TX"
logUsage "$DATE" "RX" "$RX"

After that I installed MySQL and created the following table:

CREATE TABLE `vpn_usage` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user` varchar(50) CHARACTER SET latin1 NOT NULL,
  `date` datetime NOT NULL,
  `rx` bigint(20) unsigned NOT NULL DEFAULT '0',
  `tx` bigint(20) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `user` (`user`,`date`)
) ENGINE=InnoDB AUTO_INCREMENT=190 DEFAULT CHARSET=utf8
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.