Download Latest Version cch-0.6.tar.gz (603.1 kB)
Email in envelope

Get an email when there's a new version of cch

Home
Name Modified Size InfoDownloads / Week
README 2011-09-11 13.3 kB
cch-0.6.tar.gz 2011-09-11 603.1 kB
Totals: 2 Items   616.5 kB 0
CCH v0.6 - Connections using Custom Handshaking

== CONTENTS

* Overview
* License
* Package Contents
* Details
* Blocking RST/ICMP Responses
* Building
* Patching BIND
* Building BIND
* Running / Configuring The Broker
* Sample command line
* Common Problems
* Todo's


== OVERVIEW

This utility was used as part of a presentation I made at CISCon 2011. It 
allows the creation of an otherwise normal TCP connection between two 
firewalled clients. Moreover, it offers a working example of using DNS for 
command and control messaging.

A firewalled client is able to create a TCP connection with the outside world 
because the initiating packet (SYN) pokes a limited hole in the firewall 
protecting the client. The firewall is then expecting and will allow a 
response from whatever peer the client was attempting to reach (SYN/ACK). 
Once the client accepts that response and completes the handshake (ACK), the 
firewall will allow data to flow between the two hosts in either direction.

The reason two firewalled clients aren't normally able to create a TCP 
connection is that their respective firewalls are configured to drop the 
other's initial requests (SYN packets). However, even though the remote peer's
firewall drops the initial SYN, the local client's firewall will still accept 
a response (SYN/ACK) from the remote peer. 

CCH leverages this by ignoring the fact that the initial requests aren't 
received and responding anyway. This requires a fair amount of out-of-band 
coordination between the two peers but DNS can be user to provide this. 

Once those coordinated responses are received, each of the clients' firewall 
behaves as if their peer has just initiated a perfectly normal TCP connection. 
This allows, as one would expect, full communication between the two entirely 
firewalled clients.


== LICENSE

This code is provided under the GPL3 license. See the file COPYING for a
copy of the license.


== PACKAGE CONTENTS

./cch			- The main.c file (everything else is packaged as a lib)
./lib			- The source code for the library.
./include		- The header files needed by the library.

./demo			- Some descriptive slides and a packet capture (image).
./firewall		- Some useful scripts for testing.
./named			- Patch files / sample configuration for named (Coordinator).

 
== DETAILS

CCH uses a technique similar to that used by Skype and other P2P applications
to poke holes in your firewall from the inside out. It's slightly different
in that it creates a TCP connection instead of a UDP hole.

It also demonstrates how easy it is to use DNS for "out of band" messaging.
In order to make the connection process work, the peers must be coordinated
in time, and share compatible connection parameters.

The time coordination and exchange of parameters is done using DNS messaging.
Each peer "registers" to connect on an "end point" with the connection broker. 
The peer identifies the port and IP to use (the SEQ/ACK pair is derived from 
this information, in order to minimize the amount of data that needs to be
exchanged). After registering, the peer goes into a "ping" mode, in which 
it repeatedly queries the coordinator for status. This is roughly similar to 
a server listening on a port.

When the second peer registers on the end point, each side receives a
"CONNECT" response to it's next status "ping". This response contains the
remote peer's port and IP (from which the SEQ/ACK pair are derived), and a
delay counter intended to cause the peers to try and connect within a few
seconds of each other.

The coordinator is implemented using a patched version of BIND9's "named"
program. The hooks that are added watch for requests that include a 
familiar segment (*.lb.domain.tld). The "lb" segment is used to indicate
the request should be delegated to the connection broker, and not processed
as part of the normal named DNS query/answer processing.

Once the peers begin the connection sequence, the normal SYN/SYN-ACK/ACK
handshake is replaced with:

 Connection Open Sequence
 
  		Initiator										Peer
  		---------										---------
  	t0	SS				------ S:1000:0     ---->|		SS
  						|<---- S:2000:0     ------
 
  	t1	SAS				------ SA:1000:2001 ----->		SAR
 
  	t2					<----- SA:1001:2000 ------
 
  	t3					------ A:1001:2001  ----->
 
  	t4					<----- A:2001:1001  ------
 
  	tC	1001:2001										2001:1001

At time 0 (t0), both peers send a SYN packet. This packet exits the local
firewall, but is dropped by the remote firewall. This conditions the local
firewall to be in the SYNSENT state, expecting a response from the "server".

At t1, the initiator (chosen based on a function of the two IP/port pairs, 
which both sides have knowledge of) sends a SYN/ACK packet. This is allowed
to enter the remote firewall. Why not? It's exactly what's expected by the
peer in response to the SYN that was sent.

At t2, the non-initiator peer sends a SYN/ACK packet. This, from the
perspective of the remote firewall, looks very reasonable and is allowed
through. The unexpected outbound SYN/ACK that was sent at t1 does not affect 
this.

At t3 and t4, ACK packets are exchanged to complete the "normal" handshake
and establish the connection. At tC (connected), both sides are operating
in the ESTABLISHED state with the expected SYN/ACK parameters.

== BLOCKING RST/ICMP RESPONSES

CCH works by using packet sniffing and packet injection techniques. Your 
kernel doesn't know about this, and gets very irritated by the seemingly
erroneous packets being sent to it and by it. In response, it will send
packets with the RST flag set to reset what appears to be a superfluous
connection.

The script "quiet-port.sh" in the "firewall" subdirectory will configure
your local firewall to block outgoing RST packets to avoid this. If these
packets are sent, and the firewall sees them, it will void the connection
state we are trying to establish, and CCH won't work.

You might at this point wonder why the firewall isn't sending ICMP packets 
or RST packets on it's own, when it receives the original SYN packet from 
the CCH peer. If it did, this would cause the other firewall to disregard 
it's connection state for the attempted NEW connection, and CCH would fail. 
Fortunately, thanks to nmap and lot's of eager scanners, almost no one 
obeys that requirement of the TCP specification, and packets are silently 
dropped. There are other strategies for coping with this (a low TTL in the 
initial SYN) that I would like to add to CCH, but so far it's not been 
necessary. 


== BUILDING

This package was developed and tested under Ubuntu (9.04 and 10.04). At
one time, it was also tested under Debian, and worked, but it has not 
been tested recently.

To build this code, use:

tar -xzvf cch-0.6.tar.gz
cd cch-0.6
./configure
make && make install

Alternatively, you may wish to use --prefix to put the include files
and cch bin file in the /usr/include and /usr/bin directories:

./configure --prefix /usr

You will also need to build a modified version of bind9 to act as the 
connection "broker" (see the details below for an explanation). 


== PATCHING BIND

The connection broker is implemented using a fully functional version of 
bind9. Certain types of requests are intercepted, and passed to a module
(cchcoordinator.c) in the CCH library code. This module handles parsing
the request and coordinating the peers. An "answer" is then passed
back through the bind9 code as a response to the query.

This is loosely shrouded to look like it has something to do with a 
load balancing algorithm, and is contained in "balance.c". A hook function
in "balance.c" is called from the named file "query.c".

To implement this, the makefile for named has to be modified to include
the file balance.c and balance.o in the appropriate macros. This is done
by modifying the Makefile.in file, which is used to generate the Makefile.

In ./bind9/bin/named/Makefile.in, edit the following macros to include 
the additional file "balance.c/balance.o":

OBJS = ......... balance.@O@ \
SRCS = ......... balance.c \

You also have to indicate that named has to be linked with the cch 
library, by adding it to the DNSLIBS macro:

DNSLIBS = ....................... -lcch

Once the balance.c file is added, and the query.c is patched to include
the call to the hook function (refer to the included query.c file for
a reference of where to put it -- it may be different in your version
of bind9), the named program should build.

	WARNING--> Don't just include the version of query.c that's provided
	with the source. Make sure to compare it to the version in your 
	bind9 distribution, to ensure your not using an old version of 
	query.c.  


== BUILDING BIND

The files added to the named build require the cch include files. The 
easiest way to make this work is to perform the following steps:

#1) Build CCH

tar -xzvf cch-0.6.tar.gz
cd cch-0.6
./configure
make && make install
cd ..

#2) Extract and patch the BIND package

tar -xzvf bind9-package.tar.gz          <-- Expands into bind9?
cp cch-0.6/named/*.c bind9/bin/named/.  <-- Use matching name (bind9)

cd bind9
ln -s ../cch-0.6/include/cch cch		<-- Link to include files 

cd bind9/bin/named
vi Makefile.in                          <-- Patch as described above

#3) Build bind

cd ../..								<-- Now in "bind9" directory
./configure 
make && make install
 

== RUNNING / CONFIGURING THE BROKER

The broker is expected to respond to DNS "Well Known Service" queries, 
that take the form:

xxxxxx.lb.domain.tld

The "lb" segment is used as a sentinel value within balance.c to indicate
that this request should be "brokered", and not processed through normal
bind9 processing.

To make this work, you MUST include a wild card WKS record in your domain
configuration similar to the 2nd line below:


www		A	10.0.1.1			; You may have a similar line for your site 
*.lb	WKS	10.0.1.1	6 1023	; <-- Essential to trigger the broker.

It doesn't really matter what the IP address is, but it is reasonable to 
make it the same as your web server, or other related IP. The goal of 
using the WKS record is to make it seem "normal" for the DNS server to 
answer the query, with the data hidden in the WKS bitmap. The PING request 
made to the coordinator actually uses common service bits (like SSH and WWW) 
to make it seem more "normal". The actual exchange of connection information 
requires more "bandwidth", so more bits are used, but this is only done once 
per connection, when the coordinator indicates the peer is ready to connect.

See the cch-0.6/named/conf directory for sample configuration files.


== SAMPLE COMMAND LINE

The following command lines can be used to connect to each other, assuming
that one command is run on a 10.0.1.x network, and the other is run
on a 192.168.1.x network. Each must have access to the DNS server providing
the connection broker.

On the 10.0.1.x network (host IP 10.0.1.10):
cch -cvve 1 -b private.lan -i 10.0.1.10 -p 57005


On the 192.168.1.x network (host IP 192.168.1.10):
cch -cvve 1 -b private.lan -i 192.168.1.10 -p 48879


== COMMON PROBLEMS

* Got Root?

CCH uses injection and sniffing, which requires root permissions on the box.

* Appropriate hardware/network configuration.

Because CCH uses sniffing/injection, your host-based firewall has no affect
on it's ability to see packets on the wire, or send packets. This can lead
to false positives. 

Make sure you use a "real world" environment. This can be tricky to set up
in a home lab. You need two hosts (VM's may exhibit the SAME problem caused
by CCH's ability to sniff traffic on the wire -- false positives), and two
firewalls, with a DNS server/Coordinator in the "open" network between the 
firewalls (or, at least, accessible to both peers).

Make sure you have physical wire separation. If you're using an older hub,
packets may be visible on each wire, so even though the packets may be
logically dropped by the firewalls and not "routed", the CCH sniffer may
still see them (yes, all this happened to me while testing!)

* Host Kernel Sending RST's

Make sure to use the silent-port.sh script to kill outbound RST's from
your peers, or the kernel will stifle your connections before they get
started.

* DNS access / Contacting the Coordinator

Make sure you configure the coordinator's DNS zone files appropriately, 
and do some basic tests with dig.

If you are not using a public DNS name, and are running this in a lab
environment, make sure your host's name resolver is configured to talk
to the coordinator (etc/resolv.conf). CCH uses libresolv to communicate 
with the Coordinator, so if your using an internal name, the DNS requests
have to get to the Coordinator. Normally, this is done using the regular
DNS query delegation, but you might have to help in a lab environment.

Again, use dig to check that your host resolves the name correctly (for
example, "dig private.lan").


== TODO'S

* Complete the TCP stack! The implementation in this is a proof of concept,
	and a poor one at that.
* Add 4-way (split) handshake support.
* Integrate RST firewall suppression into CCH so a script isn't needed.
* Add local port mapping so the established connection can easily be used.
* Add automatic hole generation for IDS suppression. 
* Add automated patching scripts for current versions of named source. 





Source: README, updated 2011-09-11