PPTP 流量记录

PPTP 流量记录

我在 Centos 5 机器上运行 pptpd,但我没有设置任何日志记录。

如果出现滥用行为,我需要确定哪些用户做了坏事,这意味着我需要记录所有流量。我可能有最多 20 个用户每天使用 VPN 连接至少 3 个小时。

tcpdump 是一个解决方案吗?

答案1

我没有使用过 pptpd,但我确实在 CentOS 机器上运行了 pptp,它充当向外连接到 DrayTek 路由器的客户端。

因此,我设想,对于每个连接的用户,服务器上都会创建一个相应的 ppp 网络接口来为该用户提供服务。您可以设置一些 iptables 规则来记录来自这些 ppp 接口的所有数据包。您必须从 pptpd 关联(记录)的最后一件事是特定用户被分配特定 IP 地址的时间。这样您就可以记录流量并将其链接到相应的 VPN 用户(如果您强制为 VPN 用户分配静态 IP,则更容易)。

您需要确保在每个方向上都应用日志记录规则,最有可能的是 FORWARD 链(用于记录发往 VPN 网络上其他主机的流量,这些流量由 VPN 服务器路由)。如果要包括服务器本身的日志记录,请添加 INPUT 和 OUTPUT 链(+ 表示所有 ppp 接口):

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

显然,如果您希望监控特定类型的流量,您可以定制上述 iptables 规则,使其更加特定于协议。

使用 tcpdump 在每个接口上捕获 PCAP 将会是一场噩梦。您需要发明一种激进的方法,让 tcpdump 进程在用户登录和注销时为每个创建和删除的 ppp 接口分叉并终止。我想不出一个好的方法来实现这一点,而且试图记录每个会话中的数据包内容似乎有点过头了。最好在私人网络上对它们可能连接的设备采取进一步的安全措施。

答案2

我必须实现类似的东西,但只能达到每小时记录带宽的水平。我所做的就是在 chap-secrets 中为每个传入连接设置静态 IP,然后向 iptables 添加一些规则来计数数据。

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

请注意,这些规则是从我的 Shorewall 配置中抽象出来的,可能不完全正确。

显然将 10.0.0.100 更改为用户 PPTP 会话的 IP。然后我编写了以下脚本,该脚本每分钟由 cronjob 运行一次(注意,需要 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"

之后我安装了 MySQL 并创建了下表:

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

相关内容