counting traffic to individual hosts behind a NAT router using ONLY iptables

counting traffic to individual hosts behind a NAT router using ONLY iptables

Post by C3 » Sat, 06 Sep 2003 14:24:53



Hi everyone.

I have four computer running behind a linux machine which is sharing the
internet access using NAT. I'd like to write some iptables rules that count
the number of bytes that go from the eth0 on the linux machine (internet
interface) to the individual IP addresses (via eth1). I'd also like to count
the number of outgoing internet bytes from each machine.

Can somebody please get me started in the right direction?

 I am also running a transparent proxy and if possible, would like to count
the traffic going through that as well.

Here is my current (simple) firewall script.

EXTIP=`ifconfig eth0 | awk /eth0/'{next}//{split($0,a,":");split(a[2],a,"
");print a[1];exit}'`

# Enable masquerading
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to $EXTIP
echo 1 > /proc/sys/net/ipv4/ip_forward

# Secure it
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state NEW -i ! eth0 -j ACCEPT
iptables -P INPUT DROP
iptables -A FORWARD -i eth0 -o eth0 -j DROP

iptables -t nat -A PREROUTING -i eth1 -p tcp -s 192.168.0.0/24 -d !
192.168.0.0/16 --dport 80 -j REDIRECT --to-port 8080

thanks in advance.

 
 
 

counting traffic to individual hosts behind a NAT router using ONLY iptables

Post by Horst Knobloc » Sat, 06 Sep 2003 17:56:21



[Accounting per IP Address behind NAT Gateway]

Quote:

> I am also running a transparent proxy and if possible, would like to
> count the traffic going through that as well.

Use iptables' packet and byte counters. These are the first
two numbers listed when you run "iptables -nvL".

Quote:> Here is my current (simple) firewall script.

> EXTIP=`ifconfig eth0 | awk /eth0/'{next}//{split($0,a,":");split(a[2],a,"
> ");print a[1];exit}'`

> # Enable masquerading
> iptables -F
> iptables -t nat -F
> iptables -t mangle -F
> iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to $EXTIP
> echo 1 > /proc/sys/net/ipv4/ip_forward

> # Secure it
> iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
> iptables -A INPUT -m state --state NEW -i ! eth0 -j ACCEPT
> iptables -P INPUT DROP
> iptables -A FORWARD -i eth0 -o eth0 -j DROP

> iptables -t nat -A PREROUTING -i eth1 -p tcp -s 192.168.0.0/24 -d !
> 192.168.0.0/16 --dport 80 -j REDIRECT --to-port 8080

I would rewrite it to:

IPT="iptables"

# if you want to allow clients FTP Access you should
# enable the next line to avoid problems
#
# modprobe ip_nat_ftp

# Enable masquerading
$IPT -F
$IPT -t nat -F
$IPT -t mangle -F

$IPT -P INPUT   DROP
$IPT -P OUTPUT  ACCEPT
$IPT -P FORWARD DROP

echo 1 > /proc/sys/net/ipv4/ip_forward

$IPT -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# Setup Accounting Rules
#
$IPT -N ACCOUNT
$IPT -A ACCOUNT -o eth0 --src <IP Addr 1> -j ACCEPT
$IPT -A ACCOUNT -i eth1 --dst <IP Addr 1> -j ACCEPT
[same two rules for each remaining IP Addr]
$IPT -A ACCOUNT -o eth0 --src <IP Addr 4> -j ACCEPT
$IPT -A ACCOUNT -i eth1 --dst <IP Addr 4> -j ACCEPT

# Secure it
#
# allow incoming connections from internal net to this host
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A INPUT -m state --state NEW -i ! eth0 -j ACCEPT

# allow incoming connections from internal net passing to
# the Internet, and the corresponding traffic back
#
$IPT -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCOUNT
$IPT -A FORWARD -m state --state NEW -i ! eth0 -j ACCOUNT

$IPT -t nat -A PREROUTING -i eth1 -p tcp -s 192.168.0.0/24 \
   -d ! 192.168.0.0/16 --dport 80 -j REDIRECT --to-port 8080

------- End of Script -------

This script is untested and may contain even syntax errors.
Use it at your own risk.

HTH

Ciao, Horst
--
?When pings go wrong (It hurts me too)? E.Clapton/E.James/P.Tscharn

 
 
 

counting traffic to individual hosts behind a NAT router using ONLY iptables

Post by Tomasz BE Pop » Sat, 06 Sep 2003 18:07:42



> Hi everyone.

> I have four computer running behind a linux machine which is sharing the
> internet access using NAT. I'd like to write some iptables rules that count
> the number of bytes that go from the eth0 on the linux machine (internet
> interface) to the individual IP addresses (via eth1). I'd also like to count
> the number of outgoing internet bytes from each machine.

> Can somebody please get me started in the right direction?

>  I am also running a transparent proxy and if possible, would like to count
> the traffic going through that as well.

> Here is my current (simple) firewall script.

> EXTIP=`ifconfig eth0 | awk /eth0/'{next}//{split($0,a,":");split(a[2],a,"
> ");print a[1];exit}'`

> # Enable masquerading
> iptables -F
> iptables -t nat -F
> iptables -t mangle -F
> iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to $EXTIP
> echo 1 > /proc/sys/net/ipv4/ip_forward

> # Secure it
> iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
> iptables -A INPUT -m state --state NEW -i ! eth0 -j ACCEPT
> iptables -P INPUT DROP
> iptables -A FORWARD -i eth0 -o eth0 -j DROP

> iptables -t nat -A PREROUTING -i eth1 -p tcp -s 192.168.0.0/24 -d !
> 192.168.0.0/16 --dport 80 -j REDIRECT --to-port 8080

> thanks in advance.

Try this:

IP="192.168.0.22" # example user
BYTES=`iptables -v -s -n -x -t nat | grep $IP | awk '{print $2}'`

BE

 
 
 

counting traffic to individual hosts behind a NAT router using ONLY iptables

Post by C3 » Sun, 07 Sep 2003 01:16:48


Unfortunately that script disabled connectivity for all my client machines
:)



> [Accounting per IP Address behind NAT Gateway]

> > I am also running a transparent proxy and if possible, would like to
> > count the traffic going through that as well.

> Use iptables' packet and byte counters. These are the first
> two numbers listed when you run "iptables -nvL".

> > Here is my current (simple) firewall script.

> > EXTIP=`ifconfig eth0 | awk

/eth0/'{next}//{split($0,a,":");split(a[2],a,"
Quote:> > ");print a[1];exit}'`

> > # Enable masquerading
> > iptables -F
> > iptables -t nat -F
> > iptables -t mangle -F
> > iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to $EXTIP
> > echo 1 > /proc/sys/net/ipv4/ip_forward

> > # Secure it
> > iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
> > iptables -A INPUT -m state --state NEW -i ! eth0 -j ACCEPT
> > iptables -P INPUT DROP
> > iptables -A FORWARD -i eth0 -o eth0 -j DROP

> > iptables -t nat -A PREROUTING -i eth1 -p tcp -s 192.168.0.0/24 -d !
> > 192.168.0.0/16 --dport 80 -j REDIRECT --to-port 8080

> I would rewrite it to:

> IPT="iptables"

> # if you want to allow clients FTP Access you should
> # enable the next line to avoid problems
> #
> # modprobe ip_nat_ftp

> # Enable masquerading
> $IPT -F
> $IPT -t nat -F
> $IPT -t mangle -F

> $IPT -P INPUT   DROP
> $IPT -P OUTPUT  ACCEPT
> $IPT -P FORWARD DROP

> echo 1 > /proc/sys/net/ipv4/ip_forward

> $IPT -t nat -A POSTROUTING -o eth0 -j MASQUERADE

> # Setup Accounting Rules
> #
> $IPT -N ACCOUNT
> $IPT -A ACCOUNT -o eth0 --src <IP Addr 1> -j ACCEPT
> $IPT -A ACCOUNT -i eth1 --dst <IP Addr 1> -j ACCEPT
> [same two rules for each remaining IP Addr]
> $IPT -A ACCOUNT -o eth0 --src <IP Addr 4> -j ACCEPT
> $IPT -A ACCOUNT -i eth1 --dst <IP Addr 4> -j ACCEPT

> # Secure it
> #
> # allow incoming connections from internal net to this host
> $IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
> $IPT -A INPUT -m state --state NEW -i ! eth0 -j ACCEPT

> # allow incoming connections from internal net passing to
> # the Internet, and the corresponding traffic back
> #
> $IPT -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCOUNT
> $IPT -A FORWARD -m state --state NEW -i ! eth0 -j ACCOUNT

> $IPT -t nat -A PREROUTING -i eth1 -p tcp -s 192.168.0.0/24 \
>    -d ! 192.168.0.0/16 --dport 80 -j REDIRECT --to-port 8080

> ------- End of Script -------

> This script is untested and may contain even syntax errors.
> Use it at your own risk.

> HTH

> Ciao, Horst
> --
> ?When pings go wrong (It hurts me too)? E.Clapton/E.James/P.Tscharn

 
 
 

counting traffic to individual hosts behind a NAT router using ONLY iptables

Post by Horst Knobloc » Sun, 07 Sep 2003 02:02:37



Quote:> Unfortunately that script disabled connectivity for all my client
> machines
> :)

Oops you are right, there is a bug in the script.




[...]
>> # Setup Accounting Rules
>> #
>> $IPT -N ACCOUNT
>> $IPT -A ACCOUNT -o eth0 --src <IP Addr 1> -j ACCEPT
>> $IPT -A ACCOUNT -i eth1 --dst <IP Addr 1> -j ACCEPT
>> [same two rules for each remaining IP Addr]
>> $IPT -A ACCOUNT -o eth0 --src <IP Addr 4> -j ACCEPT
>> $IPT -A ACCOUNT -i eth1 --dst <IP Addr 4> -j ACCEPT

Should be replaced by

$IPT -N ACCOUNT
$IPT -A ACCOUNT -o eth0 --src <IP Addr 1> -j ACCEPT
$IPT -A ACCOUNT -i eth0 --dst <IP Addr 1> -j ACCEPT
etc. for the other remaining 3 IP Addresses.

Ciao, Horst
--
?When pings go wrong (It hurts me too)? E.Clapton/E.James/P.Tscharn

 
 
 

counting traffic to individual hosts behind a NAT router using ONLY iptables

Post by C3 » Sun, 07 Sep 2003 08:28:46


The script runs ok now. thanks :)

But there are a couple of problems. The main one being that traffic is not
counted by the clients when their web browsers are not set to use a proxy,
since they are being put through my transparent proxy. The only way I can
get traffic to count is to specify to use my ISP's proxy server (which I
don't want to do because they charge for all traffic through it).

Since outgoing requests on port 80 from the clients are all redirected to
port 8080 on my server with iptables, would there be a way to write some
sort of rule that basically says "count any incoming traffic on eth0 as part
of the IP address on the local network that sent the request"?

This is a tough one!

The other problem is minor in comparison: traffic to/from the server isn't
counted (i.e. when I log into the server and use lynx, the byte counters for
192.168.0.1 do not change)

thanks for your help, Horst.



> > Unfortunately that script disabled connectivity for all my client
> > machines
> > :)

> Oops you are right, there is a bug in the script.




> [...]
> >> # Setup Accounting Rules
> >> #
> >> $IPT -N ACCOUNT
> >> $IPT -A ACCOUNT -o eth0 --src <IP Addr 1> -j ACCEPT
> >> $IPT -A ACCOUNT -i eth1 --dst <IP Addr 1> -j ACCEPT
> >> [same two rules for each remaining IP Addr]
> >> $IPT -A ACCOUNT -o eth0 --src <IP Addr 4> -j ACCEPT
> >> $IPT -A ACCOUNT -i eth1 --dst <IP Addr 4> -j ACCEPT

> Should be replaced by

> $IPT -N ACCOUNT
> $IPT -A ACCOUNT -o eth0 --src <IP Addr 1> -j ACCEPT
> $IPT -A ACCOUNT -i eth0 --dst <IP Addr 1> -j ACCEPT
> etc. for the other remaining 3 IP Addresses.

> Ciao, Horst
> --
> ?When pings go wrong (It hurts me too)? E.Clapton/E.James/P.Tscharn

 
 
 

counting traffic to individual hosts behind a NAT router using ONLY iptables

Post by Horst Knobloc » Tue, 09 Sep 2003 07:42:04



Quote:> The script runs ok now. thanks :)

> But there are a couple of problems. The main one being that traffic is
> not counted by the clients when their web browsers are not set to use a
> proxy, since they are being put through my transparent proxy. The only
> way I can get traffic to count is to specify to use my ISP's proxy server
> (which I don't want to do because they charge for all traffic through
> it).

The behavior was according your original description (at
least as I understood it). It is no problem to change this,
though.

Quote:> Since outgoing requests on port 80 from the clients are all redirected to
> port 8080 on my server with iptables, would there be a way to write some
> sort of rule that basically says "count any incoming traffic on eth0 as
> part of the IP address on the local network that sent the request"?

> This is a tough one!

> The other problem is minor in comparison: traffic to/from the server
> isn't counted (i.e. when I log into the server and use lynx, the byte
> counters for 192.168.0.1 do not change)

This is not possible because the login- and the http-connection
are independent connections.

The easiest is to count the traffic entering and leaving your
internal interface. However this is not entirely correct with
respect to your second problem, but it is as closely as you
can get.

The accounting-part of the script should look like:

# Setup accounting Rules
#
# account traffic to this host and the outbound traffic
# to the Internet per IP
#
$IPT -t mangle -A PREROUTING -i eth1 --src <IP1> -j RETURN
same rule for other remaining IP addrs

# account traffic from this host and the inbound traffic
# from the Internet per IP
#
$IPT -t mangle -A POSTROUTING -o eth1 --dst <IP1> -j RETURN
same rule for other remaining IP addrs

# Secure it
#
# allow incoming connections from internal net to this host
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A INPUT -m state --state NEW -i ! eth0 -j ACCEPT

# allow incoming connections from internal net passing to
# the Internet, and the corresponding traffic back
#
$IPT -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A FORWARD -m state --state NEW -i ! eth0 -j ACCEPT

$IPT -t nat -A PREROUTING -i eth1 -p tcp -s 192.168.0.0/24 \
   -d ! 192.168.0.0/16 --dport 80 -j REDIRECT --to-port 8080

BTW: This only works with kernel 2.4.18 and later.

Ciao, Horst
--
?When pings go wrong (It hurts me too)? E.Clapton/E.James/P.Tscharn

 
 
 

counting traffic to individual hosts behind a NAT router using ONLY iptables

Post by C3 » Tue, 09 Sep 2003 17:26:11


Once again, thanks for your help.

I have one final question. Since only a limited number of services run on
the server, would it be possible to exclude them from traffic counting? They
are TCP only services running on ports 80, 110, 139 and 2001.

Do you think then that I would have an accurate figure of the amount of
internet traffic generated by my local machines?

cheers,

C3


> > The script runs ok now. thanks :)

> > But there are a couple of problems. The main one being that traffic is
> > not counted by the clients when their web browsers are not set to use a
> > proxy, since they are being put through my transparent proxy. The only
> > way I can get traffic to count is to specify to use my ISP's proxy
server
> > (which I don't want to do because they charge for all traffic through
> > it).

> The behavior was according your original description (at
> least as I understood it). It is no problem to change this,
> though.

> > Since outgoing requests on port 80 from the clients are all redirected
to
> > port 8080 on my server with iptables, would there be a way to write some
> > sort of rule that basically says "count any incoming traffic on eth0 as
> > part of the IP address on the local network that sent the request"?

> > This is a tough one!

> > The other problem is minor in comparison: traffic to/from the server
> > isn't counted (i.e. when I log into the server and use lynx, the byte
> > counters for 192.168.0.1 do not change)

> This is not possible because the login- and the http-connection
> are independent connections.

> The easiest is to count the traffic entering and leaving your
> internal interface. However this is not entirely correct with
> respect to your second problem, but it is as closely as you
> can get.

> The accounting-part of the script should look like:

> # Setup accounting Rules
> #
> # account traffic to this host and the outbound traffic
> # to the Internet per IP
> #
> $IPT -t mangle -A PREROUTING -i eth1 --src <IP1> -j RETURN
> same rule for other remaining IP addrs

> # account traffic from this host and the inbound traffic
> # from the Internet per IP
> #
> $IPT -t mangle -A POSTROUTING -o eth1 --dst <IP1> -j RETURN
> same rule for other remaining IP addrs

> # Secure it
> #
> # allow incoming connections from internal net to this host
> $IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
> $IPT -A INPUT -m state --state NEW -i ! eth0 -j ACCEPT

> # allow incoming connections from internal net passing to
> # the Internet, and the corresponding traffic back
> #
> $IPT -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
> $IPT -A FORWARD -m state --state NEW -i ! eth0 -j ACCEPT

> $IPT -t nat -A PREROUTING -i eth1 -p tcp -s 192.168.0.0/24 \
>    -d ! 192.168.0.0/16 --dport 80 -j REDIRECT --to-port 8080

> BTW: This only works with kernel 2.4.18 and later.

> Ciao, Horst
> --
> ?When pings go wrong (It hurts me too)? E.Clapton/E.James/P.Tscharn

 
 
 

counting traffic to individual hosts behind a NAT router using ONLY iptables

Post by Horst Knobloc » Thu, 11 Sep 2003 04:56:33



Quote:> Once again, thanks for your help.

You are welcome.

Quote:> I have one final question. Since only a limited number of services run on
> the server, would it be possible to exclude them from traffic counting?
> They are TCP only services running on ports 80, 110, 139 and 2001.

Put the following rule at the beginning of the accounting
rules

$IPT -t mangle -A PREROUTING -i eth1 --dst <server ip> -p tcp \
   -m multiport --dports 80,110,139,2001 -j RETURN

$IPT -t mangle -A POSTROUTING -o eth1 --src <server ip> -p tcp \
   -m multiport --sports 80,110,139,2001 -j RETURN

Quote:> Do you think then that I would have an accurate figure of the amount of
> internet traffic generated by my local machines?

Check it yourself, you have the counter values not me. ;-)
Sum up the accounting values per direction and compare them
against the sum of INPUT and inbound FORWARD, and the sum
of OUTPUT and outbound FORWARD values.

These values should not differ too much. Eg. one reason is
that the DNS traffic originating from the server/packet
filter machine can't be accounted per IP.

Another approach is to account traffic in the FORWARD chain
(like in my first solution) and account the proxy traffic
by matching the destination port in INPUT/OUTPUT chains
on eth1 per IP. This might be an easier approach but is
also not entirely correct regarding the amount of the accounted
to the actual traffic.

Ciao, Horst
--
?When pings go wrong (It hurts me too)? E.Clapton/E.James/P.Tscharn

 
 
 

counting traffic to individual hosts behind a NAT router using ONLY iptables

Post by Horst Knobloc » Thu, 11 Sep 2003 09:06:59




[...]
>> Do you think then that I would have an accurate figure of the amount of
>> internet traffic generated by my local machines?

> Check it yourself, you have the counter values not me. ;-)
> Sum up the accounting values per direction and compare them
> against the sum of INPUT and inbound FORWARD, and the sum
> of OUTPUT and outbound FORWARD values.

Ok, it is slightly more involved.

You need to replace the following rule
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
by
$IPT -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED \
   -j ACCEPT  # incoming traffic from Internet - IN
$IPT -A INPUT -i eth1 -m state --state ESTABLISHED,RELATED \
   -j ACCEPT  # incoming traffic from internal net

and the following rule
$IPT -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
by
$IPT -A FORWARD -i eth0 -m state --state ESTABLISHED,RELATED \
   -j ACCEPT  # inbound forward - IN
$IPT -A FORWARD -i eth1 -m state --state ESTABLISHED,RELATED \
   -j ACCEPT  # outbound forward - OUT

add to the OUTPUT chain the following rule:
$IPT -A OUTPUT -o eth0 -j ACCEPT # outbound to Internet - OUT

Then add the traffic for the rules marked with OUT and
add the traffic for rules marked with IN.

Compare the OUT traffic with the traffic in the PREROUTING
chain for all IPs, and the IN traffic with the traffic in
the POSTROUTING chain for all IPs.

Ciao, Horst
--
?When pings go wrong (It hurts me too)? E.Clapton/E.James/P.Tscharn