TCP/IP Connection
cutting on Linux Firewalls and Routers
(Introducing "Cutter 1.03")
By Chris Lowth, June 2003 (Updated: April 2005)
Summary
Network security administrators sometimes need to be able to abort
TCP/IP connections routed over their firewalls on demand. This would
allow them to terminate connections such as SSH tunnels or VPNs left in
place by employees over night, abort hacker attacks when they are
detected, stop high bandwidth consuming downloads - etc. There are many
potential applications.
This article describes how a Linux IPTables based firewall/router
can be used to send the right combination of TCP/IP packets to both ends
of a connection to cause them to abort the conversation. It describes
the steps required to perform this task, and introduces a new
open-source utility called "cutter" that automates the process.
Important Warning
The technique documented here, and the software referred to are designed for "legal" and "appropriate"
use by network security administrators and the like. It has been written as part of a larger Linux firewall
project, targetting at controlling traffic from peer-to-peer software such as Kazaa, iMesh and others into
and out of a private network. It is
not designed as a tool for malicious use and the author in no way sanctions such use.
Users of the software should be aware that it's actions are easily detectable using a number of readily
available network monitoring tools, and it makes no attempt to disguise it's actions. Malicious use of "cutter"
could result in a jail sentance in a number of countries around the world.
The author cannot be held responsible for inapropriate use of the documented technique or software (whether
in it's original form, or modified).
Introduction
The use of linux systems as IP network firewalls and routers is
becoming increasingly popular. The cheapness of the software and
hardware combine with the flexibility and reliability of Linux's
networking support to make such a solution highly attractive. It is
often possible to deliver routing and fire walling facilities at a
fraction of the cost associated with systems provided by industrial
heavy-weights such as Cisco, Nortel and others.
For the knowledgeable, an out-of-the-box linux distribution such as
"RedHat" has many of the features required to build highly personalized
firewalls. For the less adventurous; there are cut-down distributions
available that are designed specifically for this task. The UK based
"SmoothWall" and it's clone "IPCop" are good examples of such an
approach; they are highly optimized distributions that include a tiny
subset of the software commonly installed by the likes of RedHat, but
add a powerful web-based front end for the tasks of configuring and
managing the system. These solutions are ideal for small office or home
networks.
One advantage of using a Linux system in this way is the ease with
which it can be extended or modified. Software can be downloaded from
the Internet for free, compiled and installed onto the system to add
features such as web proxying (Smoothwall and IPCop already have this),
content filtering, anti-virus measures or any other feature you desire.
I have recently been working on a solution to the problems of
peer-to-peer traffic filtering on a Linux firewall, and have had to
develop a "connection cutter" as part of the system, and it is this tool
that is described in this page.
What is a "TCP/IP connection cutter"?
Consider a "client workstation" system in a private network,
connected to a server on the public Internet, as in the picture below.
The connection passes through the firewall which has two network cards
- one connected to each network.
The job of the firewall is typically to ensure the safety of the
systems on the private network, and the security of any information held
on them. It is common for firewalls to be set up to allow the hosts on
the private network more or less unrestricted use of services on the
public Internet while setting very tight limits on what private systems
can be accessed from the outside world.
Firewalls often use a network address mapping technique ("NAT") in
order to allow the private addresses to be hidden from the outside
world. For example; when the user of the client at 10.0.0.2 accesses the
server at 100.1.2.3, the messages that the server receives lead it to
believe that it is being accessed by a host with address 200.4.5.6 - ie
the public side of the firewall. The firewall "messes about with"
(technical term!) the network traffic that passes through it in order
to allow this little deception to work.
A TCP/IP connection cutter is a software tool that can be run on the
firewall to forcibly abort the connection between the server and the
client. This is done in a way that leaves both ends believing that it
was the other that initiated the abort. Only a device that sits in the
path of the connection (such as the firewall in our example) can do
this.
The ability to abort a connection in this way can be useful to
firewall administrators for any number of reasons. For example...
-
A firewall administrator identifies
that a workstation on his network is using a service on the public
network that should not be permitted. He can force the closure of the
connection. This might be because of the network bandwidth being used,
or the nature of the service or some other reason that fits the
organization's security policy.
-
Or: a firewall administrator can
forcibly close SSH tunnels or VPNs that rogue employees leave open
over night between their office desktops and home networks. This can
be a real problem, and it is a well known access route into private
networks.
-
Or a web server administrator can request that a rogue incoming
connection is terminated without having to "kill" the web server
process on the server.
A connection cutter is NOT a way for rogue systems to terminate
connections made by others - it must be run on one of the routers
through which the connection passes and as such has limited application
for attackers interested in denial-of-service exploits.
How to kill a TCP/IP connection using
"IPTables REJECT with RESET"
Simply put: Fire the
"RST" bullet.
At the most basic level, it's dead easy - just send an "RST" packet
to both ends of the connection.
The TCP/IP protocol defines a packet called "RST", which is short
for "Reset". When an RST packet arrives on a connection it is
understood to mean that something has gone badly wrong and that the
application should abort the conversation. "Badly wrong" means
something like a protocol error, unrecoverable corruption, breaks in
the circuit etc. The RST packet does not include information about the
nature of the problem but is simply a kind of "Panic button" that tells
it's recipient to stop talking.
But we cant take the first shot, or
shoot on someone else's behalf
Since RST packets present such a golden opportunity for attack, most
systems will insist that the sequence number information contained in
the packet, and the address from which it comes contain good "expected"
values. Some systems even check the layer 2 MAC address before agreeing
to act on the instruction to reset. These measures make RSTs harder to
"spoof". In fact, the normal RST-sending logic embedded in the Linux
kernel (and, I imagine: others) is to send RSTs only in response to
incoming packets - that way, the sequence number can be guaranteed to
be correct.
IPTables as a possible "gun" (but not
a perfect one)
One solution for a Linux router using IPTables is to define a rule
that says "reject packets sent from address 100.1.2.3 to 10.0.0.2 (and
visa versa) with an RST".
To use this technique, we must..
-
Discover which IP addresses and
port numbers refer to both ends of the conversation, and the "NAT"ed
addresses that are used to present them over the subnets. All the
relevant information is held in the pseudo file /proc/net/ip_conntrack.
-
Build an IPTables rule that rejects
relevant outbound forwarded traffic by responding to it with an RST.
For our example above, the iptables command will look something like
the following (depending on how your tables are named, and the port
numbers used)..
-
Build another rule that does the
same for inbound traffic.
-
Watch the network traffic using
something like tcpdump to wait for the next incoming and outgoing
packets from both ends of the connection, and observe that IPTables
does indeed send the RST packets back, or keep a track of the iptables
counters for the rules we have created.
-
Finally; remove the IPTables rules
so that they don't interfere with future traffic or clog up precious
table space.
-
iptables -D FORWARD -p tcp
-s 10.0.0.2 --sport 3245 -d 100.1.2.3 -dport 22 -j REJECT
--reject-with tcp-reset
-
iptables -D FORWARD -p tcp -s 100.1.2.3 --sport 22 -d
10.0.0.2 --dport 3245 -j REJECT -reject-with tcp-reset
The result of all this activity is that the client end of the
conversation thinks that the server has reset the link, and the server
thinks that the client did it - so we have a clean closure of the
connection.
However, there are a couple of issues with this approach.
First: IPTables will not send an RST until an incoming or
outgoing packet arrives from the client or server for it to reject. If
the application is connected but idle - this may take many minutes or
hours to occur. An example is an SSH or telnet session where the user
is typing nothing. The connection stays "up" until the user hits the
first keystroke on the keyboard, at which point a packet is sent to the
server (via the firewall), and firewall can respond to it with an RST.
Second; we cant abort both ends simultaneously. To take the
SSH or telnet example already sited - the client will abort the
connection when it gets it's RST after the user presses a key, but the
server will know nothing about what has happened, and will still
believe the connection to be open. This situation will persist until the
server sends a packet - which it may never do.
It would be nice to be able to force the transmission of RST packets
immediately, so closing the connection even when there is no
application data being sent.
In effect, the firewall cant "shoot" it's RST bullet until client
and/or server have sent something through the firewall that allows it
to determine the sequence number that should be included in the RST
packet. Simply guessing a sequence number wont work - the client and
server will (if they are sensible) ignore the packet.
Better: How to cut a TCP/IP
connection by sending a FIN
The idea of sending an "RST" packet to both ends is good, but we
could do with a better way of getting it sent than turning on an
IPtables "reject" rule and waiting for something to arrive that the
firewall can reject. What is needed is some way of forcing the two ends
of the connection to send a packet to the firewall that IPtables can
then respond to.
There is a feature of the TCP/IP protocol that we could use to good
effect here :- If a packet (other than an RST) is received on a
connection that has the wrong sequence number, then the host responds by
sending a corrective "ACK" packet back. This "ACK" reply is designed to
put the sequence numbers at both ends back into step - and allows the
protocol to retransmit packets that got lost. This is very nice for our
needs - if the firewall sends a packet that is "correct" in all
respects except for the sequence number, then the host very helpfully
tells us what should have been used. We can then use this information
to build the RST packet that will abort the connection.
Following this idea, we can do the following..
-
Identify the IP addresses and port
numbers of the hosts at both ends of the connection, and any NATted
address that the firewall is using to present the private host to the
public network by inspecting the /proc/net/ip_conntrack file.
-
Build the IPtables rules that will
send RST packets to both ends of the connection when an incoming
packet arrives (the rules have already been described).
-
Send a packet to both
ends with bad sequence numbers.
-
use sequence_number = zero -
it's pretty much bound to be wrong (which is what we want).
-
use a FIN packet - they fairly
easy to put together and don't need to contain any "data" payload.
-
Send the packet using Layer 2
raw Ethernet access - so that the IP layers don't mess around with
the headers.
-
Wait for the hosts to respond with
their ACK, and for Iptables to send it's RST packet back.
-
Remove the newly added Iptables rules.
This procedure is better than the previous one because the effect is
immediate. We don't have to wait for the user of the offending SSH
session to press a key because we have tricked his computer into sending
us something to respond to.
But - we still have to have a process for determining when the FIN -
ACK - RST packets have done their stuff so that we can clean up the
iptables rules. Various options for doing this are possible. For
example: the rules can be left in place, while a cron job does a
periodic cleanup. Or we can "listen in" to the packet flow using Linux's
raw packet mode. I'm sure there are any number of other "clean up"
solutions that could be devised.
Better still: Without IPTables rules
It turns out that we can produce the same FIN -> ACK -> RST
sequence of packets without using Iptables to generate the RST at all -
so there are no IPTables rules to create or clean up.
The "raw packet socket" technique we have already suggested for the
sending of the FIN packet can be used to listen for the incoming ACK,
and send the resulting RST. This is how the "cutter" program works.
Cutter 1.03
Description and Synopsis
"Cutter" is an open source program that uses the FIN-ACK-RST packet
technique described above to abort TCP/IP connections routed
over the firewall or router on which it is run. It can be called using
one of the following four syntaxes..
cutter ip-address
Example: "cutter
10.10.0.45"
Cuts all connections passing through the firewall
between any ports on the specified ip-address (either a "private" or
"public" address) and any other hosts. This can be used to close down
all incoming connections to a particular server, all outgoing
connections from a particular client or all outgoing connections to a
server.
cutter ip-address port
Example: "cutter
200.1.2.3 80"
Cuts all connections to or from the
specified ip-address/port pair. This allows the user to be a little more
specific than the previous example and allows targetting of specific
services on specific hosts.
cutter ip-address-1 port-1 ip-address-2
Example "cutter
200.1.2.3 22 10.10.0.45"
Cuts all connections between
ip-address-2 and ip-address-1/port-1. This allows the user to cut
connections between a specified "client" and a particular service on a
specified host. Our example closes host 10.10.0.45's SSH connection to
server 200.1.2.3.
cutter ip-address-1 port-1 ip-address-2 port-2
Example: "cutter
200.1.2.3 22 10.10.0.45 32451"
Cuts the specific connection between
the two ip/port number pairs given.
License
Cutter 1.03 is released under the terms of GNU
GENERAL PUBLIC LICENSE Version 2 (June 1991) and comes with all the
usual freedom, openness and disclaimers associated with that license.
Status
Cutter 1.03 should be considered experimental.
The author is releasing a tool that works on the systems he has access
to (namely: IPCop and RedHat Linux), and he is seeking input on it's
use on other systems, ideas for improvement, offers of sponsorship -
etc.
How you can help me
The utility is issued free of charge. If you find it useful, please
consider helping me by using the www.lowth.com website as your gateway
to Amazon.com and Amazon.co.uk when you buy books, music, computers etc
from them. This costs you nothing extra - but Amazon pay me a small
commission on any purchases you make via this route.
Please use the following links..
If you are from another location - just choose the one nearest to
you.
Alternatively, you can make a donation towards the project using the
"PayPal" system (as used on eBay) by clicking ...
| |
|
|
Download
Please be sure to read and understand the "warning" near the top of this page before downloading
the software.
You can download Cutter sources (and a collection of pre-compiled binary versions) from ..
News and Announcements
Annoucements about new releases of this document and software (etc) will be made from time to time in the
"comp.os.linux.announce" news group. Keep an eye on this group if you wish to be informed about
updates etc.
|