Linux网络IP记帐
如何知道在我的ppp0网络或eth0 Internet链接上传输了多少数据?
如何按地址(例如123.1.2.3和123.1.2.4)设置IP记帐?
如何为每个Apache虚拟域设置IP记帐?
如何通过服务端口(http,smtp)和协议(tcp,udp,icmp)设置计费?
如何记录每台客户端计算机正在使用的流量?
您不必安装任何特殊的东西。
Linux内核附带IP记帐,它是iptables的一部分。
它是Linux防火墙软件的一部分。
在防火墙级别,您可以过滤流量并配置IP记帐。
Linux内核收集了大量有关网络流量的信息,这些信息可用于IP记帐。
您也可以使用第三方软件。
拓扑图
Internet/ISP router // // +-----------------+ +---------+ // eth1| Linux firewall | | LAN | //-----+ (Gateway) +------+ Servers | | 192.168.1.254 |eth0 | Users | +-----------------+ +---------+
(网关IP记帐)
192.168.1.254是一台基于CentOS的Linux计算机,它是Internet的网关。
它的作用是:
- 路由器
- 交通整形装置
- 防火墙功能
- " FORWARD"链上的IP记帐
ISP port 1000MBps (Enterprise rack) // // +------------+ +---------+ // eth1| Linux LB0 | | Apache1 | //-----+------------+------+---------+ | Linux LB1 |eth0 | Apache2 | +------------+ +---------+ Firewall | Mysql1 | 123.1.2.1 +---------+ 123.1.2.2 | Mysql2 | 123.1.2.3 +---------+ | memcache| +---------+
上面的设置很复杂,并且托管在企业Java应用程序的本地ISP(机架空间)上:
- lb0和lb1基于RHEL的软件负载平衡器。这两个服务器充当IP故障转移设备,防火墙和反向代理软件,以加快后端速度。 IP记帐在INPUT和OUTPUT链上配置了三个VIP(123.1.2.1、123.1.2.2和123.1.2.3)
- 123.1.2.1、123.1.2.2和123.1.2.3:虚拟IP地址(VIP)在lb0和lb1之间移动以提供服务可用性。
Apache {1,2,3..N},Mysql {1,2}
:用于存储数据,文件和Java应用程序的实际服务器。
警告!如果执行不正确,这些示例可能会阻止您的网络访问。
IP记帐需要对端口,服务,协议和网络概念有基本的了解。
本常见问题解答中列出的大多数操作是在假设它们将由运行bash或任何其他现代shell的root用户执行的前提下编写的。
所有示例都在RHEL或CentOS Linux下进行了测试;但应该可以在其他任何现代发行版下使用。
基于iptables的IP计费
您需要使用iptables(IPv4)或ip6tables(IPv6)来设置,维护和检查Linux内核中的数据包筛选器规则表。
可以定义几个不同的表。
每个表包含许多内置链,也可能包含用户定义的链。
您可以使用用户定义的链来设置IP记帐规则。
要查看您当前的iptables配置,请执行:
# iptables -L -n
要列出所有规则,请使用上面的命令。
您需要传递-v选项,它将显示其他信息:
- 接口名称(例如eth1)。
- 规则选项(如果有)。
- TOS口罩。
- 数据包和字节计数器,后缀为K,M或G。
# iptables -L -n -v
输出示例:
Chain INPUT (policy ACCEPT 73860 packets, 95M bytes) pkts bytes target prot opt in out source destination 0 0 ACCEPT udp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 0 0 ACCEPT tcp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:53 0 0 ACCEPT udp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:67 0 0 ACCEPT tcp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:67 Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 ACCEPT all -- * virbr0 0.0.0.0/0 192.168.122.0/24 state RELATED,ESTABLISHED 0 0 ACCEPT all -- virbr0 * 192.168.122.0/24 0.0.0.0/0 0 0 ACCEPT all -- virbr0 virbr0 0.0.0.0/0 0.0.0.0/0 0 0 REJECT all -- * virbr0 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable 0 0 REJECT all -- virbr0 * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable Chain OUTPUT (policy ACCEPT 54182 packets, 5660K bytes) pkts bytes target prot opt in out source destination
请注意数据包和字节列。
步骤1:创建用户定义的链
创建新的用户定义链以设置IP记帐的语法如下:
# iptables -N INET_OUT # iptables -N INET_IN
上面的命令创建了一个新的用户定义链,称为INET_OUT,以跟踪传出流量。
INET_IN可用于跟踪传入流量。
步骤2:设置IP记帐
您需要按如下所示追加INET_IN和INET_OUT:
# iptables -A FORWARD -j INET_IN # iptables -A FORWARD -j INET_OUT
FORWARD用于通过服务器路由的数据包,即您的Linux服务器充当路由器(见
网关IP记帐)。
您可以为INPUT和OUTPUT链追加以下内容:
# iptables -A INPUT -j INET_IN # iptables -A OUTPUT -j INET_OUT
步骤3:查看IP记帐数据
执行以下命令:
# iptables -L -v -n
要仅查看传出IP记帐数据:
# iptables -v -n -L INET_OUT
输出示例:
Chain INET_OUT (1 references) pkts bytes target prot opt in out source destination 2472 405K all -- any any example.com anywhere 17M 16G all -- any any lan.local anywhere
example.com生成405k字节,而lan.local生成16G传出流量。
按地址设置IP记帐
假设您有以下三个域,并且希望跟踪每个域的出站流量和入站流量:
- example.com 123.1.2.1
- example.net 123.1.2.2
- example.org 123.1.2.3
您需要在shell提示符下输入以下命令,或将其添加到shell/perl脚本中:
# /sbin/iptables -N INET_OUT # /sbin/iptables -N INET_IN # /sbin/iptables -A INPUT -j INET_IN # /sbin/iptables -A OUTPUT -j INET_OUT # /sbin/iptables -A INET_IN -d 123.1.2.1 # /sbin/iptables -A INET_IN -d 123.1.2.2 # /sbin/iptables -A INET_IN -d 123.1.2.3 # /sbin/iptables -A INET_OUT -s 123.1.2.1 # /sbin/iptables -A INET_OUT -s 123.1.2.2 # /sbin/iptables -A INET_OUT -s 123.1.2.3 # /sbin/service iptables save
要查看传入的IP统计信息,请执行:
# /sbin/iptables -v -n -L INET_IN
输出示例:
Chain INET_IN (1 references) pkts bytes target prot opt in out source destination 16M 2086M all -- any any anywhere example.com 6141K 1319M all -- any any anywhere www.example.net 30M 4657M all -- any any anywhere example.org
要查看外发IP统计信息,请执行:
# /sbin/iptables -v -n -L INET_OUT
输出示例:
Chain INET_OUT (1 references) pkts bytes target prot opt in out source destination 2472 405K all -- any any example.com anywhere 17M 16G all -- any any www.example.net anywhere 5165K 2399M all -- any any example.org anywhere
通过服务端口进行IP记帐
要收集eth1链接上承载的数据的端口80(http),443(https),22(SSH),143(imap),25(SMTP),53(dns)卷统计信息,请执行:
### create a new set of chains ### # /sbin/iptables -N INET_IN_PORT # /sbin/iptables -N INET_OUT_PORT ### ATTACH them (USE FORWARD for gateway systems) ### # /sbin/iptables -A INPUT -j INET_IN_PORT # /sbin/iptables -A OUTPUT -j INET_OUT_PORT ### Set up rules for INPUT ### # /sbin/iptables -A INET_IN_PORT -i eth1 -p tcp --dport 80 # /sbin/iptables -A INET_IN_PORT -i eth1 -p tcp --dport 443 # /sbin/iptables -A INET_IN_PORT -i eth1 -p tcp --dport 25 # /sbin/iptables -A INET_IN_PORT -i eth1 -p tcp --dport 143 # /sbin/iptables -A INET_IN_PORT -i eth1 -p tcp --dport 53 # /sbin/iptables -A INET_IN_PORT -i eth1 -p udp --dport 53 # /sbin/iptables -A INET_IN_PORT -i eth1 -p tcp --dport 22 ### Set up rules for OUTPUT ### # /sbin/iptables -A INET_OUT_PORT -o eth1 -p tcp --sport 80 # /sbin/iptables -A INET_OUT_PORT -o eth1 -p tcp --sport 443 # /sbin/iptables -A INET_OUT_PORT -o eth1 -p tcp --sport 25 # /sbin/iptables -A INET_OUT_PORT -o eth1 -p tcp --sport 143 # /sbin/iptables -A INET_OUT_PORT -o eth1 -p tcp --sport 53 # /sbin/iptables -A INET_OUT_PORT -o eth1 -p udp --sport 53 # /sbin/iptables -A INET_OUT_PORT -o eth1 -p tcp --sport 22 # /sbin/service iptables save
要查看统计信息,请执行:
# iptables -L INET_IN_PORT -v -n # iptables -L INET_OUT_PORT -v -n
按协议进行IP计费
在eth1上为tcp,udp和icmp协议设置IP记帐:
# /sbin/iptables -N INET_IN_PROTOCOL # /sbin/iptables -N INET_OUT_PROTOCOL ### ATTACH them (USE FORWARD for gateway systems) ### # /sbin/iptables -A INPUT -j INET_IN_PROTOCOL # /sbin/iptables -A OUTPUT -j INET_OUT_PROTOCOL ### Match tcp, udp and icmp ### # /sbin/iptables -A INET_IN_PROTOCOL -i eth1 -m tcp -p tcp # /sbin/iptables -A INET_IN_PROTOCOL -i eth1 -m udp -p udp # /sbin/iptables -A INET_IN_PROTOCOL -i eth1 -m icmp -p icmp # /sbin/iptables -A INET_OUT_PROTOCOL -o eth1 -m tcp -p tcp # /sbin/iptables -A INET_OUT_PROTOCOL -o eth1 -m udp -p udp # /sbin/iptables -A INET_OUT_PROTOCOL -o eth1 -m icmp -p icmp ### save them (redhat and friends only) ### # /sbin/service iptables save
要查看统计信息,请执行:
# iptables -L INET_OUT_PROTOCOL -v -n # iptables -L INET_IN_PROTOCOL -v -n
如何查看数据包和字节计数器的精确值?
使用-x选项:
# iptables -L {Chain-Name-Here} -x # iptables -L INET_IN_PORT -v -x # iptables -L INET_IN_PORT -v -x -n
输出示例:
Chain INET_IN_PORT (1 references) pkts bytes target prot opt in out source destination 274688 45080261 tcp -- eth1 any anywhere anywhere tcp dpt:http 17 1517 tcp -- eth1 any anywhere anywhere tcp dpt:https 0 0 tcp -- eth1 any anywhere anywhere tcp dpt:ssh 0 0 udp -- eth1 any anywhere anywhere udp dpt:snmp 3 228 udp -- eth1 any anywhere anywhere udp dpt:ntp
如何删除数据包和字节计数器?
使用-Z选项:
# iptables -L {CHAIN-NAME-HERE} -Z # iptables -L INET_IN_PORT -Z
验证相同,执行:
# iptables -L INET_IN_PORT -vnx
如何实时查看IP计费(带宽流量)?
您可以定期执行iptables,使用watch命令以全屏显示输出,如下所示:
# watch iptables -n -v -L INET_OUT -n # watch -n 1 iptables -v -L INET_IN
输出示例:
Portwise IP统计
Linux Apache IP记帐
请注意,我已经从上述输出中删除了域名。
按协议进行的外发IP计费
如何在重新启动后保存和还原计数器?
要保存计数器,请使用以下命令:
# iptables-save -c > /path/to/iptables.rules # iptables-restore -c You can add iptables-restore command to /etc/rc.local or write a sys v style script (recommended):
#!/bin/sh # # save-restore-iptables-counter # # chkconfig: 2345 08 92 # description: Save and restore iptables counters # processname: none # Note: See how to use this script : # http://www.theitroad.local/faq/linux-configuring-ip-traffic-accounting/ # Source function library. . /etc/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ "$NETWORKING" = "no" ] && exit 0 path="/etc/sysconfig/iptables.rules.counter" _restorecmd="/sbin/iptables-restore" _savecmd="/sbin/iptables-save" prog="save-restore-iptables-counter" start() { echo -n $"Starting $prog: " $_restorecmd -c < "$path" retval=$? return $retval } stop() { echo -n $"Stopping $prog: " $_savecmd -c > "$path" retval=$? return $retval } restart(){ stop start } case "" in start) start;; stop) stop;; restart) restart;; *) echo $"Usage:*filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [2027:704756] :INET_IN - [0:0] :INET_OUT - [0:0] :INET_IN_PORT - [0:0] :INET_OUT_PORT - [0:0] :INET_IN_PROTOCOL - [0:0] :INET_OUT_PROTOCOL - [0:0] :RH-Firewall-1-INPUT - [0:0] -A INPUT -j INET_IN -A INPUT -j INET_IN_PORT -A INPUT -j INET_IN_PROTOCOL -A INPUT -j RH-Firewall-1-INPUT -A FORWARD -j RH-Firewall-1-INPUT -A OUTPUT -j INET_OUT -A OUTPUT -j INET_OUT_PORT -A OUTPUT -j INET_OUT_PROTOCOL # IP accounting apache -A INET_IN -d 123.1.2.1 -A INET_OUT -s 123.1.2.1 # Port wise ip accouting -A INET_IN_PORT -i eth0 -p tcp -m tcp --dport 80 -A INET_OUT_PORT -o eth0 -p tcp -m tcp --sport 80 # protcol wise ip accouting -A INET_IN_PROTOCOL -i eth0 -m tcp -p tcp -A INET_IN_PROTOCOL -i eth0 -m udp -p udp -A INET_IN_PROTOCOL -i eth0 -m icmp -p icmp -A INET_OUT_PROTOCOL -o eth0 -m tcp -p tcp -A INET_OUT_PROTOCOL -o eth0 -m udp -p udp -A INET_OUT_PROTOCOL -o eth0 -m icmp -p icmp # Unlimited to lo -A RH-Firewall-1-INPUT -i lo -j ACCEPT # ICMP -A RH-Firewall-1-INPUT -i eth0 -p icmp --icmp-type echo-reply -j ACCEPT -A RH-Firewall-1-INPUT -i eth0 -p icmp --icmp-type destination-unreachable -j ACCEPT -A RH-Firewall-1-INPUT -i eth0 -p icmp --icmp-type time-exceeded -j ACCEPT # ICMP ping reply -A RH-Firewall-1-INPUT -i eth0 -p icmp --icmp-type echo-request -j ACCEPT # Drop spoof -A RH-Firewall-1-INPUT -i eth0 -s 10.0.0.0/8 -j LOG --log-prefix "IP DROP SPOOF A: " -A RH-Firewall-1-INPUT -i eth0 -s 10.0.0.0/8 -j DROP -A RH-Firewall-1-INPUT -i eth0 -s 172.16.0.0/12 -j LOG --log-prefix "IP DROP SPOOF B: " -A RH-Firewall-1-INPUT -i eth0 -s 172.16.0.0/12 -j DROP -A RH-Firewall-1-INPUT -i eth0 -s 192.168.0.0/16 -j LOG --log-prefix "IP DROP SPOOF C: " -A RH-Firewall-1-INPUT -i eth0 -s 192.168.0.0/16 -j DROP -A RH-Firewall-1-INPUT -i eth0 -s 224.0.0.0/4 -j LOG --log-prefix "IP DROP MULTICAST D: " -A RH-Firewall-1-INPUT -i eth0 -s 224.0.0.0/4 -j DROP -A RH-Firewall-1-INPUT -i eth0 -s 224.0.0.0/5 -j LOG --log-prefix "IP DROP SPOOF E: " -A RH-Firewall-1-INPUT -i eth0 -s 224.0.0.0/5 -j DROP -A RH-Firewall-1-INPUT -i eth0 -s 127.0.0.0/8 -j LOG --log-prefix "IP DROP LOOPBACK " -A RH-Firewall-1-INPUT -i eth0 -s 127.0.0.0/8 -j DROP # Drop INVALID packets immediately -A INPUT -i eth0 -p ALL -m state --state INVALID -j LOG --log-prefix "IP DROP INVALID " -A INPUT -i eth0 -p ALL -m state --state INVALID -j DROP -A INPUT -i eth0 -p tcp ! --syn -m state --state NEW -j LOG --log-prefix "IP DROP SYN " -A INPUT -i eth0 -p tcp ! --syn -m state --state NEW -j DROP -A INPUT -i eth0 -p tcp --tcp-flags ALL NONE -j LOG --log-prefix "IP DROP TCPFLAGS:1 " -A INPUT -i eth0 -p tcp --tcp-flags ALL NONE -j DROP -A INPUT -i eth0 -p tcp --tcp-flags ALL ALL -j LOG --log-prefix "IP DROP TCPFLAGS:2 " -A INPUT -i eth0 -p tcp --tcp-flags ALL ALL -j DROP -A INPUT -i eth0 -p tcp --tcp-flags ALL FIN,URG,PSH -j LOG --log-prefix "IP DROP TCPFLAGS:3 " -A INPUT -i eth0 -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP -A INPUT -i eth0 -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j LOG --log-prefix "IP DROP TCPFLAGS:4 " -A INPUT -i eth0 -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP -A INPUT -i eth0 -p tcp --tcp-flags SYN,RST SYN,RST -j LOG --log-prefix "IP DROP TCPFLAGS:5 " -A INPUT -i eth0 -p tcp --tcp-flags SYN,RST SYN,RST -j DROP -A INPUT -i eth0 -p tcp --tcp-flags SYN,FIN SYN,FIN -j LOG --log-prefix "IP DROP TCPFLAGS:6 " -A INPUT -i eth0 -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP -A INPUT -i eth0 --fragment -p ICMP -j LOG --log-prefix "IP DROP ICMP FRAGMENT " -A INPUT -i eth0 --fragment -p ICMP -j DROP # Open port and other stuff -A RH-Firewall-1-INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A RH-Firewall-1-INPUT -s 0/0 -i eth0 -p udp -m state --state NEW -m udp --dport 53 -j ACCEPT -A RH-Firewall-1-INPUT -s 124.1.2.3 -i eth0 -p udp -m state --state NEW -m udp --dport 161 -j ACCEPT -A RH-Firewall-1-INPUT -s 124.1.2.3 -i eth0 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT -A RH-Firewall-1-INPUT -s 0/0 -i eth0 -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT -A RH-Firewall-1-INPUT -s 0/0 -i eth0 -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT -A RH-Firewall-1-INPUT -s 0/0 -i eth0 -p tcp -m state --state NEW -m tcp --dport 53 -j ACCEPT -A RH-Firewall-1-INPUT -s 0/0 -i eth0 -p tcp -m state --state NEW -m tcp --dport 25 -j ACCEPT -A RH-Firewall-1-INPUT -s 0/0 -i eth0 -p tcp -m state --state NEW -m tcp --dport 143 -j ACCEPT -A RH-Firewall-1-INPUT -s 0/0 -i eth0 -p tcp -m state --state NEW -m tcp --dport 110 -j ACCEPT -A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited COMMIT #end{start|stop|restart}" exit 3 esac
示例Redhat/CentOS/Fedora特定的配置文件-/etc/sysconfig/iptables
iptables -N YOUR-CHAIN-HERE iptables -A FORWARD -j YOUR-CHAIN-HERE iptables -A YOUR-CHAIN-HERE -d IP-ADDRESS iptables -A YOUR-CHAIN-HERE -s IP-ADDRESS iptables -A YOUR-CHAIN-HERE -i ppp0 -p tcp -m tcp --sport PORT iptables -A YOUR-CHAIN-HERE -o ppp0 -p tcp -m tcp --dport PORT iptables -A YOUR-CHAIN-HERE -i ppp0 config-options-as-per-requirements
语法总结
对网关系统IP记帐使用以下语法:
iptables -N YOUR-INPUT-CHAIN-HERE iptables -N YOUR-OUTPUT-CHAIN-HERE iptables -A INPUT -j YOUR-INPUT-CHAIN-HERE iptables -A OUTPUT -j YOUR-OUTPUT-CHAIN-HERE iptables -A YOUR-INPUT-CHAIN-HERE -d IP-ADDRESS iptables -A YOUR-OUTPUT-CHAIN-HERE -s IP-ADDRESS iptables -A YOUR-CHAIN-HERE -i eth1 config-options-as-per-requirements
对专用服务器角色或复杂的托管解决方案使用以下语法:
##代码##