# (solved) iptables / Asterisk iax / DNAT & PREROUTING pro

## tgice

Augh.  Pulling my hair out!

I just set up a rather important test installation where I've got two Gentoo boxen running 2.6.11-gentoo-r9 as routers & VPN endpoints (using the kick ass OpenVPN package).  After some hassling around (as usual, it was iptables related), I got most things working right.  I also have Apache / email / dns, and a few other things running on one of them.

Here's my big problem.  Behind the Apache server is another Gentoo box running only the Asterisk PBX system.  I'm trying to forward, in a 'pinhole' kind of way, just a few UDP ports through to the Asterisk box so that I can answer VOIP calls at that location, over the (single) IP address that the router machine has.

I'm of course doing SNATting in iptables with that router machine so that all of the other PC clients behind it have internet access, but I also need to implement a couple of DNAT rules to route incoming traffic on the Asterisk iax port (I'm using 4569).  

So I put rules in something like this to accompish that task:

 *Quote:*   

> $IPTABLES -A FORWARD -p udp -d $LAN_ASTERISK \
> 
>   --dport 4569 -j ACCEPT
> 
> ...
> ...

 

$LAN_ASTERISK is the IP of the Asterisk machine, of course, and $INET_ROUTER is the external IP of the router box.

I've tested by firing up tcpdump, filtering on port 4569, and initiating a VOIP connection from the outside.  Immediately, I start seeing the 4569 packets hitting the router box, but they don't get recognized by my iptables rules..  They totally skip that PREROUTING rule for 4569.  They're *definitely* UDP 4569 packets showing in tcpdump.

If I use, e.g., the knock client to just send a very simple (I think empty, really) udp packet to 4569, that at least will hit the rule, and if I switch the '-j DNAT' to LOG, I can see the packets correctly in my log and know that iptables is correctly identifying them based on the criteria.

Furthermore, on the real VOIP tests to the box, after a few minutes, I'll get 'packet died' messages in the log that refer to the 4569 packets.  This is because of another rule I've got specified that logs packets that don't get delivered within 3 minutes or something.  But the strange thing is, those logged packets show a source of what I'd expect, but the destination has now been rewritten to the router machine's *local* lan address (again, not the same as the Asterisk machine's LAN addr).  Oh, and they do still (of course) show a 4569 source and dest port.

So the main question is, does anyone have any idea why the deuce iptables is stubbornly ignoring those 4569 udp packets even though I've written the same PREROUTING rule about 15 different ways to try to capture them.  I'm not even sure that this is anything peculiar to Asterisk, it may have something to do with UDP, but I don't know.

Anyway, I know this is a ton of info, but I figured someone may have an idea of what I'm blathering on about or may know of some extra tools I could use or strategies I could employ.

Thanks.

jlLast edited by tgice on Wed Jun 22, 2005 7:09 pm; edited 1 time in total

----------

## tutaepaki

Are you sure the packets you are seeing dropped from the undeliverable rule are not responses from your asterisk box. Maybe the packets are getting through to the server, and it's the responses being dropped. Should be easy enought to test by running tcpdump on the asterisk box?

If that's the case....check your postrouting NAT rules, maybe you're applying them to the internal interface too?

----------

## tgice

Yeah, I should've mentioned that.  I also ran tcpdump on the Asterisk box.  No dice.  Never even sees the packets.

From the iptables reading I've done, I've gathered that the PREROUTING rules (or w/e one calls them) are the first hit, right?  I mean even before INPUT or any of the other ones, so I can't see how *anything* would be interfering with those packets and getting them to go down the normal chains (and eventually get timed out).

Thanks for the response.

----------

## DaveArb

 *tgice wrote:*   

> 
> 
> ```
> $IPTABLES -A FORWARD -p udp -d $LAN_ASTERISK \
> 
> ...

 

In your PREROUTING line, try "udp" in lower case. I'm not sure iptables will accept it uppercased.

Dave

----------

## tgice

Thanks for the suggestion, but I don't think that's the problem.  With iptables-1.2.11-r3, anyway, it doesn't have a problem with case sensitivity on the packet type.  I know this b/c:

  a) I don't get errors when I run the command I showed you,

  b) the correct rule shows up, labeled with udp and

  c) as I mentioned in the original post, I am able to capture simple 4569/udp packets with that rule that

      are sent with (e.g.) the port knocking client (which allows you to push a tcp or udp access to arbitrary

      ports).

----------

## DaveArb

Here's a PREROUTING that I know works, from my gateway firewall to a mail server (in save format):

```
-A PREROUTING -p tcp -i eth0 --destination-port 25 -j DNAT --to 192.168.0.6:25
```

My FORWARD is a tiny bit different than yours:

```
-A Forward-Firewall -i eth0 -p tcp --dport 25 -d 192.168.0.6 -j ACCEPT
```

(Forward-Firewall is jumped to from FORWARD)

I've specified my incoming ethernet port. Unfortunately, it's been long enough since I set this up, I don't recall if its really necessary or not.

Dave

----------

## tgice

Yeah, I don't think you actually have to specify the interface, although believe me, I've tried just about every possible permutation, I think.  If you don't, I think it just defaults to listening to all, and you'll see that represented by an '*' in the:

```
iptables -L -v
```

output.  Oh, also, I've successfully done PREROUTING stuff before.  I've got another router box that's in an even more complicated situation where it's managing multiple external IPs and doing PREROUTING to route that traffic to the appropriate internal boxen.  And, frustratingly, that all works fine, and this situation just doesn't want to.

I'm reasonably sure that my problem here is not due to some simple typos or misunderstanding of the PREROUTING concept.  Now, I've of course been wrong before and I don't mind trying to eliminate that as a source of the problem, but what I really think would help me is if I could get some tips on how to chase this down perhaps at a low iptables level and figure out why the hell it's not classifying those packets as it obviously appear they should be.

Alas, I'm at a loss still.

----------

## DaveArb

I guess what I'd do (which might not be interesting, given my spectacular lack of success thus far  :Wink: ) is:

1) Turn off iptables altogether and ensure that the box can even route to that Asterisk machine's IP (I'm a big fan of starting at the most basic.)

2) Turn iptables back on with logging turned on for all rules, and see what's generated.

It's bizarre, I sure cannot see a problem in what you've published, and have to take your word that what you haven't is all good.

Dave

----------

## tgice

That's a good idea, and I'll have to admit I hadn't really taken the time to do that, even though I know that's one of the first places to go.

So I just ran a quick test (remotely, glad I didn't screw up and get locked out of the box, that might've been problematic).  Anyway, I flushed all of the chains completely and only loaded two rules.  A SNAT one so that my clients inside could still connect to the internet while I'm testing and the other DNAT one we've been talking about.  I did a LOG DNAT one just to see if the chain would capture anything.

Here's what: 

```
iptables -t nat -L -v
```

 gives me after loading those rules (iptables -L -v shows everything empty, ACCEPT all):

```
Chain PREROUTING (policy ACCEPT 21 packets, 1405 bytes)

 pkts bytes target     prot opt in     out     source               destination

    0     0 LOG        udp  --  any    any     anywhere             anywhere

        udp dpt:4569 LOG level debug prefix `xxx TEST #1 : '

Chain POSTROUTING (policy ACCEPT 8 packets, 536 bytes)

 pkts bytes target     prot opt in     out     source               destination

   11   609 SNAT       all  --  any    eth1    anywhere             anywhere

        to:000.000.000.000
```

Now, I've always seen the  4569/udp packets coming in with tcpdump, and I still saw them in this config of 

course, only problem is after I see several of them flowing over the iface, like so:

```
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth1, link-type EN10MB (Ethernet), capture size 68 bytes

11:46:01.558191 IP xxx.xxx.com.4569 > yyy.yyy.com.4569: UDP, length:

12

11:46:01.559070 IP xxx.xxx.com.4569 > yyy.yyy.com.4569: UDP, length:

12

11:46:03.586228 IP xxx.xxx.com.4569 > yyy.yyy.com.4569: UDP, length:

12
```

(note the damnable 4569 port and the UDP type!), I recheck the nat PREROUTING stats, and look:

```
Chain PREROUTING (policy ACCEPT 74 packets, 4932 bytes)

 pkts bytes target     prot opt in     out     source               destination

    0     0 LOG        udp  --  any    any     anywhere             anywhere

        udp dpt:4569 LOG level debug prefix `xxx TEST #1 : '

Chain POSTROUTING (policy ACCEPT 129 packets, 9365 bytes)

 pkts bytes target     prot opt in     out     source               destination

   43  2587 SNAT       all  --  any    eth1    anywhere             anywhere

        to:000.000.000.000

Chain OUTPUT (policy ACCEPT 146 packets, 10656 bytes)

 pkts bytes target     prot opt in     out     source               destination
```

No packets captured by the PREROUTING rule whose only criteria is dpt:4569/udp!  So, as I'd figured, it's not something really simple, or a case of another hidden rule matching these packets and stealing them.

I should mention (though I doubt this would affect the problem) that my inet connection is sDSL, and I've got a router which plugs directly into the line from outside, and then that router is plugged into my inet NIC on the router machine.  The guys at the provider assured me that the router is configured in some sort of bridged mode that won't touch the packets and just passes them right through, so there should be no problem there (the sDSL router is *not* doing any kind of NAT or anything funky).

I should also mention that for the past several months, I was using one of those crappy (gawd, I hate those) 3Com 3cr8xx series routers for the VPN and it was able to pass these 4569/udp packets over itself (from the same sDSL router configuration) without a problem.

I know this is unlikely, but I'm beginning to think there may be some sort of bug in iptables or the kernel parts that I'm using on this.  Has anyone heard of strange routing/iptables problems with kernels in the 2.6.11-gentoo-r9 vicinity?

Other than that, I'm completely at a loss here.  I'm still holding out for a real simple forehead smack solution to this problem.

----------

## DaveArb

It's been a long time since I've set up a Gentoo router (the machine I posted of earlier has 402 day uptime, and it wasn't close to new when it was moved). I apologize if this is obvious or out of date. Maybe it will jar something loose.

/etc/conf.d/iptables - used to have to set ENABLE_FORWARDING_IPv4="yes" here. I don't recall if the machine's ability to SNAT implies this is correct or not.

On my gateway machine, when I run the '-L -v' like you did, I get a "to:<IP>" field. I notice yours doesn't have this, and wonder why.

Damn, I wish my memory were better, because it sure should be pretty easy.

Dave

----------

## tgice

Pfffh.  I gave up on my memory a long time ago.  I now know to rely heavily on notes for anything that's important.  Heh.  Sure would like one o' them photographic memories, but oh well.

About the conf.d/iptables enable forwarding option.  I'm using the generic way of doing this (I assume), which is to just do this:

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

I do it on every init.d/iptables load.  I think that enables me for forwarding fine, though I'm guessing that probably is an issue I'd have to deal with later anyway, since I'm still convinced there's some problem happening way up front with these PREROUTING rules.

Oh, and to answer the last question about not showing a '-to:<IP>', I assume you're talking about the PREROUTING rule, since the POSTROUTING rule did have one.  And that's just b/c I wasn't actually doing DNAT in that PREROUTING rule, I was just doing a LOG, to kick out detail to the syslog if it hit those packets.  The point is, either way, I think I should be seeing those packets getting picked up with those criteria in the PREROUTING and they're not.

----------

## DaveArb

My caution about echoing to ip_forward is that it kind of isn't The One Right Gentoo Way, if you know what I mean? I used to do it the same, and for some reason stopped and put it into the conf.d file. I've decided that although Gentoo is fairly vanilla in setup, my life as admin is a lot easier if I do things the way they are set up to run. YMMV.

I misunderstood WRT your PREROUTING, I thought you added the log in addition to the actual route. I'm afraid I got nothing on this one, wish you best of luck.

Dave

----------

## tutaepaki

The only table to see the packet before the nat/PREROUTING is mangle/PREROUTING, so just check that there's nothing in the mangle table. Just in case  :Wink: 

You could also try taking the port specification off the LOG rule in the nat table so you log EVERYTHING that hits the table.

FYI : Packets go...

NETWORK -> mangle/PREROUTING -> nat/PREROUTING -> Routing decision

and from there, either into...

mangle/INPUT -> filter/INPUT -> local process -> Routing decision -> mangle/OUTPUT -> nat/OUTPUT -> filter/OUTPUT or...

mangle/FORWARD -> filter/FORWARD and then to...

mangle/POSTROUTING -> nat/POSTROUTING -> NETWORK

----------

## tgice

Okay, I finally got this working, the only problem is, I'm not sure I can explain exactly why what I tweaked caused things to start working.

The (first) machine I kept referring to with the firewall that wouldn't seem to recognize the 4569 packets was on one side, with Asterisk behind it.  The other (second) machine that I was using to test the VOIP calls was at a whole different site, with a very similar iptables setup (setup by me), the only difference being it was running Asterisk on the same box.  So it wasn't behind NAT in the same way.

What I ended up doing was changing the bindaddr Asterisk was using (on the second machine, not the first) in iax.conf to the local (192.168.x.x) address instead of what it was before, bound to all addresses (0.0.0.0).  Once I did this, everything seemed to magically start working.  I could make VOIP calls in both directions.

I think what was going on had to do with the fact that the second machine (also running Asterisk) is in a more complex situation than the first.  It's managing 3 or 4 external IP addresses, routing for a whole network (although it's mostly low volume), etc.  It also responds locally to two of the external IPs, one for the router (SNAT) and one for itself (on a domain I host on that machine).

So, the point is, whatever happened, the packets must've started coming across from the 2nd to the 1st machine somehow looking different because of how Asterisk created them, knowing it was listening to just one local address now.

I'll also have to cop to fiddling a bit with a few of the iptables rules on the 2nd machine's side, but I'm pretty sure they really didn't change anything, or they at least didn't until I also made the Asterisk IP listen change.

Also, I'd kind of gotten on to that tack of thinking after noticing that a software (diax softphone) client on a regular (nat) client machine behind the 2nd firewall *would* successfully connect to the 1st network's Asterisk, even when my 2nd Asterisk wouldn't.  The only difference was, its packets had the router IP address, and not the second external IP that the 2nd machine's firewall was using.

Anyway, I'm happy, for now.  Assuming this'll be reasonably stable and I can shift things around without breaking it.  Sorry for the rambling explanation, but as always, I hope this may be of some use to someone with similar problems down the road.

And now I just have to clear up some problems with active FTP on the original firewalled machine!  Woohoo!  (See my other post on that, if you like: https://forums.gentoo.org/viewtopic-t-351979.html)

Thanks to all the responders so far.

----------

