Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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

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

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
iptables -A fw2vpn -d

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

Obviously changing 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):


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

        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)"
                local QUERY="INSERT INTO vpn_usage (user, date, tx) VALUES ('%s', '%s', %d) ON DUPLICATE KEY UPDATE tx=tx+VALUES(tx)"

        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

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`)
share|improve this answer

Your Answer


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.