Key Pages: [ Rope Home Page | Basics (tutorial) | Language Reference | Download ]


Development of 'rope' was suspended in Feb 2009, but work is now restarting as time permits - watch this space.

An Example Rope Script

The script below shows a number of the features of ROPE being used to check the content-length header in HTTP transfers in order to match those that exceed a specified size. Using this script, Iptables is able to identify HTTP transfers that would exceed a configured maximum by inspecting the first packet of the transfer. This means that they can be blocked before they get significantly under way.

It first verifies that the data portion of the packet starts with a valid HTTP header, then it inspects each "key: value" pair in the HTTP header in order to identify the content-length. If this is found, then the length string is converted to an integer and compared against the "max allowed" value configured on the first line of the script. If the transfer's content length is higher than the configured value, the packet is deemed to match.

The script also handles partial downloads by inspecting the content-range header in order to determine the files total length.

Script Source

Here is the source of the script we are going to use.

1000000		# match on content-size larger than this

########################################################

$m put	# store the configured content-size

# Is this a real HTTP reply? Check the first line

"HTTP/1." expect_str                         # do we start "HTTP/."?
1 lift, dup "0" eq, swap "1" eq, or assert   # next should be "0" or "1"
" " expect_str                               # then a space
{isdigit} expect_while                       # then some digits
{isprint} expect_while                       # then some printable chars
if (1 lift "\r" ne { $offset dec } )         # then possibly a "\r"
"\n"	expect_to                            # then a "\n"

# Yes it is - so start to pull the header apart, looking for
# the content-length field.

0 $s put  # $s will hold the content-length (size) if we find it.
1 $h put  # $h is a boolean - are we "in" the HTTP header?

repeat(20 {	# limit the search to 20 fields (anti-DOS)

	expect_one(
		# Detect end of headers, and flag $h false
		{ expect_str( "\r\n" ) 0 $h put yes }
		{ expect_str( "\n" )   0 $h put yes }

		# Detect the content-length and pull out the
		# length value. Put it in $s
		{
			expecti_str( "content-length:" )
			expect_while( {isspace} )
			expect_while( {isdigit} ) atoi $s put
			expect_to( "\n" )
			yes
		}

                # Handle partial content
                {
                        expecti_str( "content-range:" )
                        expect_while( {isspace} )
                        expecti_str( "bytes" )
                        expect_while( {isspace} )
                        expect_while( {isdigit} )
                        expect_str( "-")
                        expect_while( {isdigit} )
                        expect_str( "/")
                        expect_while( {isdigit} ) atoi $s put
                        expect_to( "\n" )
                        yes
                }

		# just accept (but skip) any other header
		{ expect_to( "\n" ) yes }
	)

        dropall # clean up the stack

	# If we hit the end of the headers - we didnt find it
	if ( $h not { no } )

	# If the content-length is bigger than our cieling, then
	# we have a match.
	if ( $s $m gt {
		println(
			"iptables::rope - Large file: size = " $s
			", from " $ip_saddr ipv4_ntoa ":" $tcp_source
			" to " $ip_daddr ipv4_ntoa ":" $tcp_dest
		)
		yes
	} )
})

# If we didnt see content-length within out limited scan, then
# report back no match
no

Compiling The Script

Once the above script has been entered, it should be compiled and saved in the appropriate directory. This is done using the "ropec" command, like this (see Compiling).

 ropec -i contlen.rope

Specifying The Iptables Rule

Once the script has been compiled, an Iptables rule can use it to match packets, for example, the following rule looks for TCP/IP packets coming in on interface eth0, with a source port of 80 (http) and that are matched by our rope script.

iptables -A FORWARD -p tcp \
            -i eth0 \
            --sport 80 \
            -m rope --script contlen \
            -j DROP

Scroll to Top