Ascend Pipeline Router Filter Tutorial
By: Ted Felix

On September 18, 2001 my router got hit hard by the NIMDA worm. HTTP requests kept coming in on port 80. These were from the worm who was looking for M$'s web server, "IIS". A strange sequence of events was occurring, however that was keeping my "1 cent/minute" ISDN line connected, so I had to determine the cause of the problem and stop it.

Apparently my Ascend Pipeline router was responding to http packets destined for IP addresses in my static block that I was not currently using. The response was an ICMP Destination Unreachable packet. This is perfectly fine, however, the incoming http packets and the outgoing ICMP packets were keeping my connection up by resetting the router's idle timer.

What to do? Install a filter or two on the router, right? Much easier said than done. Unless I've totally missed it someplace, the Ascend router manual is completely useless when doing this sort of thing. So I decided to experiment and carefully document my findings. These are them.

All this info is based on a Pipeline 50 (P50-1UBRI) router running 6.0.13 firmware. I also used the 6.0 documentation to try and figure this stuff out. My Pipeline 50 is set up as an IP router on an ISDN dialup line. I have a block of 5 or 6 static IPs from my provider, only three of them are normally in use.

The Manuals

The Ascend Router manuals are obnoxiously vague when explaining the filtering features. Some example filters are given, but nowhere is there a clear and complete explanation of how the filters are really processed internally by the router. In addition there are errors in the manual's explanation of filters. What follows is information I've been able to determine by experimenting at length with my Ascend Pipeline 50.

Oh and one more thing. Those menus in the router make no sense at all. They are totally disorganized. They drive me crazy. Even so, I refuse to use the Java config utility because I don't trust it.

Packet Flow

Without knowing where filters fit into the flow of network traffic within the router, you are going to be surprised when the filters you so carefully wrote don't work as expected. Here's what I've been able to determine.

WAN
 |
 +-- wanDisplay (in wanDisplay format, 4 octet header)
 |
 +--> Connection Call Filter ---> Call Control (idle timer and dialup)
 |
Outbound Connection Data Filter (?)
 |
 +--> Internal Router Processing
 +<-- (destination unreachable responses, etc...)
 |
Inbound Connection Data Filter 
 |
Ethernet Filter (?)
 |
Ethernet

The following version shows the bidirectional nature of the data flow. This was suggested by a reader of this page. He may have done a better job, I need to dig up his version.

   WAN
   A |
   | |
  wanDisplay (in wanDisplay format, 4 octet header)
   | |
  Connection Call Filter ---> Call Control (idle timer and dialup)
   | |
   X----- Outbound Connection Data Filter (?)
   | |
   | +--> Internal Router Processing
   +<---- (destination unreachable responses, etc...)
   | |
   | X--- Inbound Connection Data Filter 
   | |
  Ethernet Filter (?)
   | |
   | V
 Ethernet

I'm not too sure about the location of the Outbound Connection Filter. It seems to go there since after getting my filter working I noticed that wanDisplay no longer showed outbound ICMP/destination unreachable packets going out. However, it might actually go prior to the Connection Call Filter. We would need to experiment with two filters, one set as the Outbound Connection Data Filter, and one as the Connection Call Filter to see if this is the case.

One interesting thing that is obvious from the above diagram is that an inbound connection data filter can't affect packets going into the router's internal processing. However, these packets do indeed affect the call status causing an interesting problem if someone is constantly hitting you with bad packets.

The Ascend manual cryptically states that data filters take precedence over call filters. I believe this is false. It is certainly true for the most common case, that of controlling a call based on outbound traffic (the diagram agrees with this). But for controlling a call based on inbound traffic, the manual is undoubtedly wrong. Judging from how little the manual has to say about filters in general, it's not surprising that there would be errors. The manual writers obviously don't really understand filters.

Diagnostics

Pressing Ctrl-D gives you the "Do Menu". Press "D" to get the diagnostics interactive prompt ">". From here you can type "help ascend" and see a list of all the "hidden" diagnostic commands. Just typing "help" only shows a subset of the available diag commands. Two of these commands are very useful in working with filters, "wanDisplay" and "wdDialout".

wanDisplay shows the packet flow in between the WAN and any connection data filter. So inbound traffic won't be filtered before it hits wanDisplay, but outbound traffic will be filtered. The format of wanDisplay's output includes a 4-byte header (I believe this is an ISDN header of some sort) followed by IP packets (or possibly other stuff if you are bridging IPX or something equally strange). Note that this format does not match the format of packets hitting "Generic" filters, so don't use the offsets you get from wanDisplay when writing Generic filters.

wdDialout is important because it shows the format of the packets as they will be seen by a Generic filter. Without wdDialout, you have no idea where the IP header begins when setting up a Generic filter. wdDialout's format includes a 14-byte header which has a source MAC address (6-bytes), a destination MAC address (6-bytes) and a two byte packet type identifier. It has been a while for me, but this might be a standard 802.3 ethernet packet header.

I thought at one point I was aware of some way of dumping ethernet traffic using the router. But this may not actually be possible.

Where can filters be used?

Before a filter can be used, it must be defined. You can define filters by going to Ethernet | Filters and picking a filter to edit.

There are at least three places you can use filters. First is in a connection's "Data Filter" option (Ethernet | Connections | *pick one* | Session Options... | Data Filter). Second is in a connection's "Call Filter" option (Ethernet | Connections | *pick one* | Session Options... | Call Filter). Thirdly, a filter can be placed on the Ethernet interface itself (Ethernet | Mod Config | Ether Options... | Filter).

I assume that Ethernet filters can be used to protect the router from traffic on the Ethernet. This could be used to prevent users from telnetting into the router, or as an added set of 12 filters in addition to the 12 Outbound Connection Data Filters. On the inbound side, this basically gives you an additional 12 filters.

Call filters

Simply put, if a packet passes through a call filter, it keeps the call connected. The default call filter (Call Filter=0) allows all incoming and outgoing packets through (they keep the call connected). If you are constantly getting hit by a worm, your connection will stay up as long as the worm is hitting you.

Internal Router Behavior

Beware, that the router's own behavior is prior to inbound data filtering. So, if the router is causing you trouble, data filtering might not solve the problem. However, a carefully thought out combination of data filtering and call filtering should help with almost any connection-related problems.

In my example, I was receiving port 80 http requests for invalid IP addresses, and the router bounced them back. Both the inbound http requests and the outbound bounce packets were keeping the (rather expensive) phone line connected.

At first I tried a data filter to block all inbound http requests. This failed (as expected) because the requests still made it into the Call Filter, and they also made it into the router's internal processing which generated the bounce packets and sent them out. It appeared to me that my filter did nothing. Actually, it did stop http requests from getting further than the router, so all my personal firewalls on my network were happy.

Next I decided to try this same inbound http blocking filter as a Call Filter. That didn't work either. The inbound packets didn't keep the call up, but the outbound bounce packets from the router's internal processing did. Now you can see how the Ascend manuals are seriously lacking when you are trying to deal with a situation such as this. Only the diagram above can help you here.

At this point I knew I would need an outbound ICMP/Destination Unreachable filter to stop the internal router processing from affecting the connection. Once I had this filter, I set it up as both the Connection's Call Filter and Data Filter. As a call filter, this prevents inbound http requests and outbound ICMP/Destination Unreachables from keeping the connection up. As a data filter, it keeps inbound http requests from getting on my network and it also blocks outbound ICMP/destination unreachable packets from the router or anyone else on my network. A workable set of effects.

Overall Filter Processing

A packet is evaluated against each filter in order from first to last. If the packet is never allowed to pass by a filter, it will not be passed.

For a filter set that looks for specific things, and doesn't let them pass, you will find that the last filter will be a generic all pass filter. This is so the packets that weren't filtered out by the previous filters can get through.

For a filter that allows a broad range of packet types, there will typically be a few filters that define what can pass, and no drop filters. This is because everything that doesn't pass one of the filters is dropped.

The manual says that filters "are applied in filter-number order", which is true. But then it goes on to say that "if a packet does not match any of the defined conditions in a filter, it is forwarded as usual." This is not at all what happens. If a packet is not handled by a filter, it is dropped.

IP Filters

The IP filter works as expected. The packet is tested against each of the criteria, and if it passes all, then the action specified is taken (pass or drop).

; This means, "ignore the IP address"
Src Mask=0.0.0.0
Src Adrs=0.0.0.0
Dst Mask=0.0.0.0
Dst Adrs=0.0.0.0

IP address masks and addresses set to all 0's will always pass because given an IP address X, X and 0 will always equal 0.

; Check for a source address of 216.8.32.55
Src Mask=255.255.255.255
Src Adrs=216.8.32.55
Dst Mask=0.0.0.0
Dst Adrs=0.0.0.0

If you want to test for a specific IP address, set the mask to all ones (255.255.255.255) and specify the address.

; Check for a source address on the 216.8.32.0 Class C network
Src Mask=255.255.255.0
Src Adrs=216.8.32.0
Dst Mask=0.0.0.0
Dst Adrs=0.0.0.0

If you want to test for a range of addresses, reduce the bits in the mask as needed. In the above example only source IP addresses on the class C 216.8.32 network will be selected. This could be used to allow or disallow traffic from a particular network.

Protocol=6

The IP protocol field must be a value from 0 to 255. It seems that there is no way to specify an IP filter that doesn't care about protocol. For protocols 6 (TCP) and 17 (UDP) you may use the port fields that follow.

; Check for a destination port of 80
Src Port Cmp=None
Src Port #=N/A
Dst Port Cmp=Eql
Dst Port #=80

These fields are very straightforward. First you may specify via the "Cmp" fields the sort of test you'd like to do. Choices are, none (field is ignored), Less (packet value is less than), Eql (packet value is equal to), Gtr (packet value is greater than), Neq (packet value is not equal to). The "#" fields are the values used in the comparison. In the above example, the source port is ignored, while the destination port is checked to see if it is equal to 80 (http).

TCP Estab=No

According to the manual this field specifies whether a TCP connection has to be established. I have no idea what that means.

Here is the input filter set I used to stop incoming http packets:

; First a simple IP filter to drop http traffic.
Forward=No        ; Don't pass packets meeting these criteria
Src Mask=0.0.0.0  ; Ignore Source IP address
Src Adrs=0.0.0.0
Dst Mask=0.0.0.0  ; Ignore Destination IP address
Dst Adrs=0.0.0.0
Protocol=6        ; Protocol must be 6 (TCP)
Src Port Cmp=None ; Ignore Source port
Src Port #=N/A
Dst Port Cmp=Eql  ; Destination port must equal
Dst Port #=80     ; 80 (http)
TCP Estab=No      ; A TCP connection need not be established.

; Next an all-pass generic filter.
; See the next section for an explanation.
Forward=Yes
Offset=0
Length=0
Mask=0000000000000000
Value=0000000000000000
Compare=Equals
More=No

Generic Filters

In case the filtering needed is more complicated than what is supported by the IP filters, generic filters can be used. These allow you to pass or drop packets based on specific values at specific offsets in the packet. The format of these is very straightforward.

There is one important issue to keep in mind when using Generic filters. The data packets as seen by a generic filter are the same format as what is displayed by the wdDialout diagnostic command. This means there is a 14 byte offset to the beginning of the IP header (2 MAC addresses = 12 bytes + 2 packet type bytes = 14 byte "generic header"). This may be a 802.3 ethernet header, but I'm not exactly sure.

Here's an outbound filter set I used to stop outbound ICMP/destination unreachable packets (these were keeping the line connected):

; This is the first generic filter in a chain of three.
; It checks for a valid IPV4 indicator with length 5.
Forward=No
Offset=14
Length=1
Mask=FF00000000000000
Value=4500000000000000  ; IPV4, header length 5
Compare=Equals
More=Yes

; Second in a chain of three.
; This one looks for the ICMP protocol type.
Forward=No
Offset=23
Length=1
Mask=FF00000000000000
Value=0100000000000000  ; ICMP
Compare=Equals
More=Yes

; Last of the chain of three.
; This one checks to make sure it is a
; "Destination Unreachable" packet.
; The end of the chain is indicated by More=No.
; This is probably the only filter of the chain
; where the Forward=No actually has any affect.
Forward=No
Offset=34
Length=1
Mask=FF00000000000000
Value=0300000000000000  ; Unreachable
Compare=Equals
More=No

; This is the catch-all filter that lets 
; all other packets through.
Forward=Yes
Offset=0
Length=0
Mask=0000000000000000
Value=0000000000000000
Compare=Equals
More=No

Changing filters

As the manual indicates, changes to connection data filters only take place for the next connection. This brings up an interesting situation when there is no connection at all. You must bring up the connection (possibly manually) for the change to take effect. In my experience you also have to bring it down after you bring it up. Yet another issue that can confuse whether or not you think your filter is working as advertised. It also seems as if there is a time delay before a new filter takes effect. So, connect/disconnect, then wait a minute or two before testing new filters.

Update, 8/28/2003

As of yesterday, I noticed my router staying up again. Turns out some new worm or virus performs a scan of IP addresses using ping. This worm appears to be widespread in that I get these ping scans frequently enough to keep the connection up. There are a number of new and interesting worms that have just come to life recently like LoveSan/MSBlaster, so perhaps one of those is the cause. At any rate, the router is responding with slightly different ICMP/Unreachable packets, so I updated the filters in this tutorial to cover this. I removed the check for a code of 09 on the ICMP/Unreachable (the router was returning a code of 01 this time), and I changed the check for IPv4 from just looking for the 4 to looking for the 4 and the 5, where the 5 is the Internet Header Length. This works well.

But that isn't enough. The router insists on responding to pings destined for itself, and my network's broadcast address. This then keeps the connection up. So, I set up a series of filters to stop inbound pings, and outbound pings. This then keeps the connection from staying up.

Again, this may not be enough as I am seeing more traffic on port 135 (RPC) probably due to MSBlaster. Fortunately, it only takes one IP filter to remove this on the outbound and inbound sides.

Which brings me to my point. How long before 12 filters will not be enough? I may have to come up with a more clever approach that uses fewer filters, but eliminates a larger amount of unwanted traffic.

Here's a dump of my current set of filters in config dump format (only the changes from the default are given). I haven't put the RPC filters in yet.

Name=Block http
; This one blocks inbound traffic on port 80 (http)
In filter 01...Valid=Yes
In filter 01...Type=IP
In filter 01...Ip...Protocol=6
In filter 01...Ip...Dst Port Cmp=Eql
In filter 01...Ip...Dst Port #=80
; The following 3 filters block inbound ICMP/Echo (ping)
In filter 02...Valid=Yes
In filter 02...Generic...Offset=14
In filter 02...Generic...Length=1
In filter 02...Generic...Mask=ff00000000000000
In filter 02...Generic...Value=4500000000000000
In filter 02...Generic...More=Yes
In filter 03...Valid=Yes
In filter 03...Generic...Offset=23
In filter 03...Generic...Length=1
In filter 03...Generic...Mask=ff00000000000000
In filter 03...Generic...Value=0100000000000000
In filter 03...Generic...More=Yes
In filter 04...Valid=Yes
In filter 04...Generic...Offset=34
In filter 04...Generic...Length=1
In filter 04...Generic...Mask=ff00000000000000
In filter 04...Generic...Value=0800000000000000
; The all-pass filter
In filter 05...Valid=Yes
In filter 05...Generic...Forward=Yes
In filter 05...Ip...Forward=Yes
In filter 05...Ipx...Forward=Yes
; The following three block ICMP/Unreachables
Out filter 01...Valid=Yes
Out filter 01...Generic...Offset=14
Out filter 01...Generic...Length=2
Out filter 01...Generic...Mask=ff00000000000000
Out filter 01...Generic...Value=4500000000000000
Out filter 01...Generic...More=Yes
Out filter 02...Valid=Yes
Out filter 02...Generic...Offset=23
Out filter 02...Generic...Length=1
Out filter 02...Generic...Mask=ff00000000000000
Out filter 02...Generic...Value=0100000000000000
Out filter 02...Generic...More=Yes
Out filter 03...Valid=Yes
Out filter 03...Generic...Offset=34
Out filter 03...Generic...Length=1
Out filter 03...Generic...Mask=ff00000000000000
Out filter 03...Generic...Value=0300000000000000
; The following three block ICMP/ping replies
Out filter 04...Valid=Yes
Out filter 04...Generic...Offset=14
Out filter 04...Generic...Length=1
Out filter 04...Generic...Mask=ff00000000000000
Out filter 04...Generic...Value=4500000000000000
Out filter 04...Generic...More=Yes
Out filter 05...Valid=Yes
Out filter 05...Generic...Offset=23
Out filter 05...Generic...Length=1
Out filter 05...Generic...Mask=ff00000000000000
Out filter 05...Generic...Value=0100000000000000
Out filter 05...Generic...More=Yes
Out filter 06...Valid=Yes
Out filter 06...Generic...Offset=34
Out filter 06...Generic...Length=1
Out filter 06...Generic...Mask=ff00000000000000
; All-pass filter
Out filter 07...Valid=Yes
Out filter 07...Generic...Forward=Yes
Out filter 07...Ip...Forward=Yes
Out filter 07...Ipx...Forward=Yes
END=FILT=200=0

Quick IP Decoding Tutorial

What follows is just enough information to make you dangerous when poring over hex dumps of network packets.

The following RFCs explain the format of the various TCP/IP packets:

791  Internet Protocol (IP)
792  Internet Control Message Protocol (ICMP)
761  Transmission Control Protocol (TCP)
1700 Assigned Numbers

Please note that the above RFCs (and all the information contained herein) may be obsolete when you read this. Always check the RFC status and look for the latest version.

IP Header

    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |Version|  IHL  |Type of Service|          Total Length         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Identification        |Flags|      Fragment Offset    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Time to Live |    Protocol   |         Header Checksum       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                       Source Address                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Destination Address                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Version:             4 for IPV4
IHL:                 IP Header Length in words, usually 5 implying 
                     the options field does not exist
Type Of Service:     Not very useful
Total Length:        Length from this length to the end of data
Identification:      Fragment ID, not useful
Flags:               Fragementation flags, not useful
Fragment Offset:     not useful
Time To Live:        not useful
Protocol:            1=ICMP, 6=TCP, 17=UDP See Assigned Numbers RFC 
                     for more.
Header Checksum:     not interesting
Source Address:      Where it's coming from, IP address
Destination Address: Where it's going to, IP Address
Options:             Very rarely ever seen.  Normally the IHL is set 
                     to 5, so this field doesn't exist at all.  
                     The data normally begins here.  If the IHL is 
                     larger than 5, then you need to consult the RFC 
                     for IP.

ICMP Header (IP Protocol 1)

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type      |     Code      |          Checksum             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type:  3=Destination Unreachable, 11=TTL expired, 12 parameter 
       problem, 4=source quench, 5=redirect, 8=echo (ping), 0=echo 
       reply (ping reply), 13 timestamp, 14 timestamp reply, 15 info 
       request, 16 info reply, 

TCP Header (IP protocol 6)

Source Port, Dest Port are 16-bits each and follow the IP header immediately when protocol = 6

UDP Header (IP protocol 17)

Source Port, Dest port are same as TCP, I think.

Resources

Lucent Technologies - Lucent bought Ascend. All the reference manuals and firmware downloads for Ascend's Pipeline routers are available on Lucent's tech support site.

Copyright ©2003, Ted Felix