Toastman Firmware - SSH over remote port 53 error

I normally SSH into my router from remote port 53. In most cases if not all settings this port is never blocked. Currently local dns server (dnsmasq) is using that port so I am unable to SSH via that port.

I don't want to disable dnsmasq but I would like help setting ssh to bind only to the WAN IP and not the local one. This should in theory allow me to SSH via port 53. Any help is great appreciated...

I'm a little confused by your statement. You say "I normally SSH into my router from remote port 53". The word "from" here means that your SSH client is set to bind to TCP port 53 and then issuing an SSH connection to your router (to presumably port 22). Did you mean something different (such as that you SSH into your router on port 53 (i.e. SSH is listening on TCP port 53 rather than port 22))?

If you meant to say "on the WAN side I want incoming connections to TCP port 53 to go to the SSH server, while on the LAN side I want to be able to able to SSH to the router on 192.168.1.1 (TCP port 22)", then that's easy to do: keep the SSH server listening on TCP port 22, and enable a TCP port forward for External Port 53, Internal Port 22, and Internal Address 192.168.1.1. That should only affect the WAN -- meaning from the Internet, TCP connections to {your WAN IP} port 53 will result in a connection to the SSH server on the router.

When I was testing it before I was on the LAN side and it appeared to work. Today I tried it from (port 53) work and it didn't work. Additionally, I know other people from work that can connect to their router via port 53.
Any suggestions?

I'll try doing tests of this sort myself on my own router. I should have done this before giving you the advice, although honestly my advice is fairly sound on this one. I do have some alternate ideas on settings to change, but will let you know.

Edit: Yeah, I can confirm this doesn't work, including the alternate idea I had. I have a couple more ideas, but will need to spend some time with iptables to figure them out. Note that the way to do this will probably involve adding a special line to your Administration -> Scripts -> Firewall section, rather than under Port Forwarding.

I'm really stumped on this one. I have spent almost an hour banging on this, including making use of the ipt_REDIRECT.ko module, as well as many other things. I can absolutely 100% of the time get the packets coming across the wire to be accepted (i.e. I see nat table WANPREROUTING or PREROUTING chains counters increasing for the rule), but the Internet host never received a response to the initial TCP SYN.

I seriously don't know why the hell Linux makes this so hard. This is one of the easiest things to do on FreeBSD with pf. Grrr...

I still have some other things to try and things to look at. My theory is that the packets are going out the wrong interface or possibly with an incorrect source or destination address. I'm going to need to spend some time in tcpdump.

In the meantime, if there are any folks on this forum who are deeply familiar with iptables and know how to make this work, I would really appreciate it. Quite simply the lines should be:

Please note that the "-I PREROUTING 2" entry is not a typo; I'm quite literally inserting that rule into where rule 2 is, which makes this rule precede the WANPREROUTING rule. That's all that magic is.

And like I said, the counters for this rule do increment when the connection comes in, it's just that the remote host never gets the response.

I spent some time with tcpdump, looking at all interfaces (specifically vlan2, br0, and lo). The outbound packet appears to go absolutely no where; at least that's to say, tcpdump catches absolutely nothing. So the inbound packet is indeed accepted but the Linux kernel appears to do god-knows-what with the response packet (if it even generates one -- I have no idea how to even determine if it's doing that).

tcpdump should be seeing something, regardless of what the firewall rules (i.e. filter table) rules are.

don't you have to DNAT to port 22 so the replies appear to the client to still come from 53? But if it was straight forward you could use the tomato web gui to set it up?

[edit] Things have changed over the years, if you set up remote ssh access over port 53 in the web gui it now just adds an additional "-p53" to the dropbear command line, and an additional ACCEPT line for port 53 in the INPUT chain - which is going to break the dns server.

But maybe this highlights the problem above - by default only connections from LAN are accepted on the INPUT chain, so an explicit accept for port 22 from the WAN will be needed.

Yep, and the Port Forwarding entry in the GUI uses DNAT -- yet it has the same problem: the counter increments but TCP SYN isn't responded to.

I spent a bit more time on this, and I've figured out that the filter table's INPUT chain is what's blocking the packet. I've found a workaround, but it opens up major/catastrophic issues (we're talking major here), so I'm going to try it again with the Tomato GUI / DNAT rule instead of REDIRECT.

Nope, even with the Port Forwarding entry which creates a DNAT rule, the catastrophic security issue still applies. The INPUT rule that fixes the problem but introduces a seriously major/catastrophic security hole is below. PLEASE DO NOT USE THIS RULE.

Code:

iptables -A INPUT -p tcp -i vlan2 --dport 22 -j ACCEPT

The instant this is done, connections to TCP port 53 begin working (yes you read that correctly). I should note this also fixes the issue/complication when using the REDIRECT method instead.

However, the major/catastrophic security hole that's opened is that you can also connect to TCP port 22 on the WAN IP as well.

So it doesn't appear, at least at this stage, that there's some way to say "let inbound connections to TCP port 53 in, but reject inbound connections to TCP port 22", because the INPUT rule has to be written with TCP port 22, not TCP port 53.

The only "secure" workaround I can think of at this point is to use the -s or --source flags to specify that only connections from a specific IP (i.e. the IP of the Internet machine attempting the connection to TCP port 53) should be allowed. I.e. something like this:

Code:

iptables -A input -p tcp -i vlan2 -s x.x.x.x --dport 22 -j ACCEPT

But the x.x.x.x IP (or netblock if you choose to use x.x.x.x/xx or CIDR syntax) can still connect to TCP port 22, which to me is still a problem. The whole point is to only get things to respond to on port 53.

I've been running around like a madman trying to get everything in place for Christmas break, coupled with an extra week I'm taking off at the start of the year, so I'll probably poke a sharp stick at this come this weekend (once I get all my presents wrapped, which I've got to do before relatives come into town)...

But the thought just popped into my head that allowing port 22 on the input chain might not be a bad thing IF you can block internet access to port 22 on the WAN port. Hear me out... there's a WANPREROUTING rule that sits in front of the INPUT rule, so in theory you might be able to block port 22 to $wanip or all port 22 access (since, from WANPREROUTINGs perspective, you're talking to port 53 tcp). Its not an elegant solution by any means, but it might work.

@Monk E. Boy -- if that works -- that would work until his WAN IP changes, and I don't think using -i vlan2 (e.g. without --destination and/or --source) would suffice.

The only workaround I can think for that would be to write an annoying script that goes in the WAN Up section, and it would be tricky because you'd have to handle both cases (where there's no existing firewall rule (in which case use -I (insert)), and where there already is one (in which case use -R (replace)). The -R situation is the tricky one, because you have to know the rule number, which means you end up having to do a bunch of could-mess-up nonsense with iptables -L -n --line-numbers | grep, basically. :/

Yeah, the WAN IP changing is the annoying bit, but my understanding is that WANPREROUTING only sits before the INPUT/FORWARD/etc. chains on the WAN port, so you could block port 22 in it and only affect traffic headed to the WAN port. But I've got a Christmas gift (router) to setup this weekend so that's when I'll see if it works in reality like it does in my head.

The only difference in your INPUT rule compared to mine is that you're not specifying -i vlan2.

I'll try it what you propose anyway and see the results, but based on what I've already tried, I believe the result is going to be 100% identical -- the WAN will respond on both TCP port 53 as well as TCP port 22.

That input rule will open you up to the outside as is. You need to restrict it to your lan if that's what you want. That WANPREROUTING chain acts like a subroutine. Packet hits PREROUTING first, then if it's from WAN goes to WANPREROUTING. If none of the rules there match, the packet jumps back to PREROUTING and continues on.

That input rule will open you up to the outside as is. You need to restrict it to your lan if that's what you want. That WANPREROUTING chain acts like a subroutine. Packet hits PREROUTING first, then if it's from WAN goes to WANPREROUTING. If none of the rules there match, the packet jumps back to PREROUTING and continues on.

Click to expand...

The INPUT rule I posted ends up allowing two ports opened from the WAN side -- TCP port 22, and TCP port 53. That's because the inbound packet actually gets its destination port rewritten (NAT'd I believe). This is why only one INPUT rule is needed for one port -- and that is the problem.

The OP wants this, basically:

sshd/dropbear on the router listens on INADDR_ANY, TCP port 22
SSH connections from {LAN machines} to 192.168.1.1 TCP port 22 should go to sshd/dropbear on the router itself
SSH connections from {any Internet IP} to {WANIP} TCP port 53 should go to sshd/dropbear on the router itself

And that's it. Other combinations (i.e. SSH connections from {any Internet IP} to {WANIP} TCP port 22) should not work.

Why this frustrates me: I can accomplish this using FreeBSD pf with 1 line. So why Linux is making this so difficult is beyond me.

There is no such chain called WANPREROUTING in the filter table, so the 2nd command will not work.

Possibly you're referring to either the FORWARD or wanin chain? (The wanin chain is referenced within the FORWARD chain)

If so, I'm not sure that's going to work either, because the default policy for the FORWARD chain is already DROP, and I don't see anything in included chains (i.e. wanin, etc.) that would allow this type of packet explicitly.

Does Linux internally "forward" the packet to itself (i.e. the forwarding code gets called, rewrites the packet, then gets processed by the INPUT) chain? Chain order here implies INPUT is the correct place for this:

Tried it in both the wanin and FORWARD chains (and in wanin, I made sure it was the first rule using -I wanin 0) -- nothing works in this case, and the INPUT chain continues to show dropped packets on every attempt.

The above SVG diagram, however, seems to indicate I could use the raw or mangle table PREROUTING chain to block packets destined to port 22, while the INPUT rule would allow connections to port 53. Time to try it...

(Note these rules slightly differ from my earlier post; addition of -i vlan2 to the INPUT filter, because I don't want to take any chances of packets matching another interface -- always good to specify interfaces if available)

This should also allow for your WAN IP to change without any ill effects or having to update rules. These also assume that your routers' LAN IP address is 192.168.1.1 (if it's different, change what's obvious).

The order here matters a lot, so if you get lost in my below explanation, review the above list. Effectively what I'm doing here, with the rules, is:

1. Using the raw table PREROUTING chain as a way to drop/ignore incoming packets destined to TCP port 22 on vlan2. Documentation I've read "sort of" hints that this isn't a good idea (but not as bad as doing filtering in the mangle table), but I see no other alternative.

2. Using the filter table INPUT chain to permit traffic destined to TCP port 22 on vlan2. Note that this happens last, and the ACCEPT rule is needed, because the default policy rule is DROP. Also note that the port here is 22 because the earlier nat table PREROUTING chain, using DNAT. DNAT causes the destination source and port address to get re-written (keep reading).

3. Using the nat filter WANPREROUTING chain (which is a chain used within PREROUTING; this is a "Tomato thing") to rewrite the destination address and port of certain traffic (using -j DNAT). Any traffic matching a destination TCP port of 53 gets rewritten to have a destination IP of 192.168.1.1 and a TCP port of 22. It's then handed back to the kernel for further processing (making it to the filter table INPUT chain).

(Note these rules slightly differ from my earlier post; addition of -i vlan2 to the INPUT filter, because I don't want to take any chances of packets matching another interface -- always good to specify interfaces if available)

This should also allow for your WAN IP to change without any ill effects or having to update rules. These also assume that your routers' LAN IP address is 192.168.1.1 (if it's different, change what's obvious).

The order here matters a lot, so if you get lost in my below explanation, review the above list. Effectively what I'm doing here, with the rules, is:

1. Using the raw table PREROUTING chain as a way to drop/ignore incoming packets destined to TCP port 22 on vlan2. Documentation I've read "sort of" hints that this isn't a good idea (but not as bad as doing filtering in the mangle table), but I see no other alternative.

2. Using the filter table INPUT chain to permit traffic destined to TCP port 22 on vlan2. Note that this happens last, and the ACCEPT rule is needed, because the default policy rule is DROP. Also note that the port here is 22 because the earlier nat table PREROUTING chain, using DNAT. DNAT causes the destination source and port address to get re-written (keep reading).

3. Using the nat filter WANPREROUTING chain (which is a chain used within PREROUTING; this is a "Tomato thing") to rewrite the destination address and port of certain traffic (using -j DNAT). Any traffic matching a destination TCP port of 53 gets rewritten to have a destination IP of 192.168.1.1 and a TCP port of 22. It's then handed back to the kernel for further processing (making it to the filter table INPUT chain).

Click to expand...

You probably can put this rule in WANPREROUTING (iptables -t raw -A PREROUTING -i vlan2 -p tcp --dport 22 -j DROP) since by default Tomato sends all WAN packets to WANPREROUTING by default. Having it in PREROUTING means that all packets not just WAN packets will get checked against it.

I guess I should have left the -t nat in the rule like this iptables -t nat -I WANPREROUTING -p tcp --dport 22 -j DROP

Click to expand...

Ah yeah, I see what you're doing there. Hmm. All that depends on at what point the actual address actually gets re-written by the kernel; does it happen right after a rule is executed, or does it happen at the end of the chain? If it happens at the end of a rule, then the lines you provided need to be reversed (drop things to TCP port 22 first, then for things to TCP port 53 rewrite them to TCP port 22 and move forward). If it happens at the end of a chain, then that's a different situation.

The PREROUTING chain should not be used for any filtering since, among other things, this chain is only traversed by the first packet in a stream. The PREROUTING chain should be used for network address translation only, unless you really know what you are doing.

Click to expand...

The focus here really appears to be doing all the allow/deny access in the filter table, which I understand -- however there seems to be a cat-and-mouse game with regards to rewriting packets or using things like -j REDIRECT. *shakes head*

You probably can put this rule in WANPREROUTING (iptables -t raw -A PREROUTING -i vlan2 -p tcp --dport 22 -j DROP) since by default Tomato sends all WAN packets to WANPREROUTING by default. Having it in PREROUTING means that all packets not just WAN packets will get checked against it.

Click to expand...

That's why I used -i vlan2 on the rule. It therefore only applies to inbound packets on the vlan2 interface (which is always the Internet/WAN portion). Had I not done this, the results could be catastrophic depending on where packets were coming from or going to, and to or from what interface.

vlan2, at least on my router (according to ip link show) is one of the two VLANs that makes up the physical eth0 device, and has a separate MAC compared to vlan1 (eth0 MAC=vlan1 MAC, while vlan2 MAC has its last octet increased by one). If I remember right, NVRAM variables vlanXhwname and vlanXports are what help things to physical Ethernet ports on the switch itself (and is some custom Broadcom magic).

That's why I used -i vlan2 on the rule. It therefore only applies to packets sent to the router on the vlan2 interface (which is always the Internet/WAN portion side).

Click to expand...

I understand. I was just saying that all packets will still have to be compared to the rule (of course everything not coming in on vlan2 will not match) instead of only WAN packets which are only in the WANPREROUTING chain.

(Note these rules slightly differ from my earlier post; addition of -i vlan2 to the INPUT filter, because I don't want to take any chances of packets matching another interface -- always good to specify interfaces if available)

This should also allow for your WAN IP to change without any ill effects or having to update rules. These also assume that your routers' LAN IP address is 192.168.1.1 (if it's different, change what's obvious).

The order here matters a lot, so if you get lost in my below explanation, review the above list. Effectively what I'm doing here, with the rules, is:

1. Using the raw table PREROUTING chain as a way to drop/ignore incoming packets destined to TCP port 22 on vlan2. Documentation I've read "sort of" hints that this isn't a good idea (but not as bad as doing filtering in the mangle table), but I see no other alternative.

2. Using the filter table INPUT chain to permit traffic destined to TCP port 22 on vlan2. Note that this happens last, and the ACCEPT rule is needed, because the default policy rule is DROP. Also note that the port here is 22 because the earlier nat table PREROUTING chain, using DNAT. DNAT causes the destination source and port address to get re-written (keep reading).

3. Using the nat filter WANPREROUTING chain (which is a chain used within PREROUTING; this is a "Tomato thing") to rewrite the destination address and port of certain traffic (using -j DNAT). Any traffic matching a destination TCP port of 53 gets rewritten to have a destination IP of 192.168.1.1 and a TCP port of 22. It's then handed back to the kernel for further processing (making it to the filter table INPUT chain).

I understand. I was just saying that all packets will still have to be compared to the rule (of course everything not coming in on vlan2 will not match) instead of only WAN packets which are only in the WANPREROUTING chain.

Click to expand...

What might interest you about the nat table WANPREROUTING chain is that the PREROUTING chain entry for it applies to all interfaces (not just vlan2). There is actually more processing that goes on for a packet to make it through the 7-step process (look at what phase it gets to the nat table PREROUTING chain, vs. when it reaches the raw table PREROUTING chain) -- meaning, I'm actually blocking the packet as soon as possible, i.e. no time wasted going through the mangle table). I still don't know if that's the right thing to do though. :/

Could it work in the WANPREROUTING section? Yes I think so, but the rule order matters -- the rules you provided are actually reversed. You'd want the DROP rule for TCP port 22 first, followed by the DNAT rule, otherwise you could potentially end up dropping your own rewritten packet.

That said -- I'd still like an explanation, if you have one, for why filtering rules should make it into the nat table PREROUTING chain. The docs I pointed folks to says that should not be done, and I'd love to know the justification for putting them there.

Footnote: in nat table PREROUTING chain, the very first rule (DROP rule for inbound packets on vlan2 with a destination address of the LAN network) also is bizarre. I'm still trying to wrap my head around what purpose it serves exactly -- it doesn't help with spoofed packets in any way/shape/form because there isn't a condition where those kind of packets are going to arrive on the vlan2 interface from an ISP. Routers on the Internet look at the destination address of a packet to know where to forward it, and if they can't figure out where, they forward it to their default gateway. I'd have a very different opinion if this rule was matching against the source address that matched the LAN network. Possibly this rule is just a "catch all" for very broken network configurations involving the whole eth0 <--> vlan1 / vlan2 situation (but even that doesn't make sense, since vlan1 and vlan2 have different MACs).

Could it work in the WANPREROUTING section? Yes I think so, but the rule order matters -- the rules you provided are actually reversed. You'd want the DROP rule for TCP port 22 first, followed by the DNAT rule, otherwise you could potentially end up dropping your own rewritten packet.

Click to expand...

Insert (-I) puts rules in reverse order. I.e. the last rule is actually first. So my drop rule would come before the dnat rule.

Footnote: in nat table PREROUTING chain, the very first rule (DROP rule for inbound packets on vlan2 with a destination address of the LAN network) also is bizarre. I'm still trying to wrap my head around what purpose it serves exactly -- it doesn't help with spoofed packets in any way/shape/form because there isn't a condition where those kind of packets are going to arrive on the vlan2 interface from an ISP. Routers on the Internet look at the destination address of a packet to know where to forward it, and if they can't figure out where, they forward it to their default gateway. I'd have a very different opinion if this rule was matching against the source address that matched the LAN network. Possibly this rule is just a "catch all" for very broken network configurations involving the whole eth0 <--> vlan1 / vlan2 situation (but even that doesn't make sense, since vlan1 and vlan2 have different MACs).

Click to expand...

I agree. I don't get that rule either. Nothing coming from the internet should have a destination of a LAN network. The destination would be your WAN address. That's how it would get to the router in the first place.

That said -- I'd still like an explanation, if you have one, for why filtering rules should make it into the nat table PREROUTING chain. The docs I pointed folks to says that should not be done, and I'd love to know the justification for putting them there.

Insert (-I) puts rules in reverse order. I.e. the last rule is actually first. So my drop rule would come before the dnat rule.

Click to expand...

Doh! *laugh* Yeah, funny -- I can understand the networking bits fine, but I still haven't gotten used to the -A vs. -I vs. -D vs. -R syntax with iptables (like with old FreeBSD ipfw all we had was the equivalent of append, and pf works entirely off of a config file). Yes I understand now, you're completely right. Thank you for correcting me.

Bird333, so what happens when the WAN IP changes as a result of DHCP (from the ISP)? The 2nd rule will no longer going to work, since wan_ipaddr is now different than before.

You would have to put that rule in the WAN Up script section, except you would also have to write special conditional checks (using ugly error-prone grep, etc.) to look for an existing rule of that type and replace it (using -R), otherwise insert (-I). You can't just put the line in WAN Up either, because every time your IP changes you'd insert a new rule. And don't forget about rule order too -- specifically talking about code in the dnsmasq bits (do they actually clear the INPUT chain and insert new rules, or do they use -R?)

The point here is that managing rules that use specific source or destination IP addresses -- when those addresses change dynamically -- becomes very complex very quickly. This is why I wrote the rules I did, relying entirely on interface and direction, rather than src/dst IP.

For now I'm going to have to say stick with what I proposed earlier, although I would change it to this:

Apologies for getting things crossed above, but when the router is a rate limiting spec the number of rule checks is going to have an effect on throughput since it all needs CPU checks.

Click to expand...

Step up to the plate and do benchmarks/testing first and post results. Please do between 10-15 tests in succession and provide the average, since a single comparison test (i.e. Internet speed test + CPU load test) won't be sufficient.

Else I see no other way to solve this other than through highly annoying complexities/methods. raw PREROUTING and mangle PREROUTING are the only two things that can block certain kinds of packets before having its IP and destination port rewritten by the nat WANPREROUTING DNAT rule.

Re IP changing - that shouldn't be an issue with Tomato since the firewall rules are rebuilt on wan ip change. The firewall script should be the place for these iptables commands, it should be run before the WAN is brought up else there will be a window of opportunity for a hacker to get in!

Since the firewall rules are always rebuilt it is theoretically better to SNAT rather MASQUERADE to nat the output, since the latter needs to regularly check what WAN IP it should use. However even that is very difficult to prove - so its left as a GUI checkbox in Toastman mod at least!

I have never used raw or mangle tables but I know the latter is used in Tomato for QOS.

Strikes me that if something is going to be blocked it should be blocked as early as possible - so could use raw PREROUTING?, but seems safest for the above ACCEPT/DROP pair to be in filter INPUT. I assume optimal performance is highly function of types of traffic, and there's a distinct danger of attempting to over-engineer and creating a security vulnerability.

I'm sure my router not the rate limiting step in my internet connection - to benchmark would have to build a test system, but I do suspect the order/complexity of iptable netfilter rules can be a reason why different firmwares perform differently - and tomato historically did well in tests, presumably since Jon and Thibor understood the iptables configuration!

That input rule will open you up to the outside as is. You need to restrict it to your lan if that's what you want. That WANPREROUTING chain acts like a subroutine. Packet hits PREROUTING first, then if it's from WAN goes to WANPREROUTING. If none of the rules there match, the packet jumps back to PREROUTING and continues on.

Click to expand...

This is not correct. INPUT will only be traversed for any packets with a destination address of a local interface - otherwise, it will flow through FORWARD for LAN-destined packets that aren't the local machine. The DNAT is what makes it destined for the local LAN IP of the router in the first place, so unless you mangle with WANPREROUTING, the destination IP will be the WAN IP and thus cannot ever traverse INPUT (or FORWARD, for that matter).

EDIT: Aw, crap. First time I'd ever noticed dropbear is doing this:

tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
Thus, it's by default not just listening on the LAN interface, but *every* interface, including WAN. This is not good on a huge number of levels, but it is what it is...and thus, yes, the DROP is absolutely needed.

In other news, do not ever, EVER bind a listening app to a WAN interface. This is retarded.
Ignore the post below as well, since everything was predicated on the above not being the case. Criminy.

I'm actually running OpenSSH on 192.168.1.1 (actually 172.16.0.1, but that's not germane here) so I never noticed this until I fell back to stock. Sorry for the confusion.

Re IP changing - that shouldn't be an issue with Tomato since the firewall rules are rebuilt on wan ip change. The firewall script should be the place for these iptables commands, it should be run before the WAN is brought up ...

Click to expand...

The official Tomato FAQ entry isn't clear enough -- it just states ambiguously "whenever there are changes that affect the firewall" which is way too open-ended. I'm therefore left with the impression, hopefully, that the Firewall script section gets executed after DHCP negotiation with the ISP -- but I refuse to just assume that. What comes into play is what tables and chains get flushed/emptied and recreated and when. This isn't documented anywhere; for example, I can tell for a fact that table nat chain PREROUTING has to get flushed/rewritten (I can tell because the DHCP-negotiated IP is used as a destination address in those rules), but table filter chain INPUT is a different story altogether.

The only way to find out, it seems, is to go and look at the bloody source code.

Also, as far as Jon/Thibor/etc. "understanding the iptables configuration", that's putting a lot of blind faith into things. There's already evidence in this thread that there may be rules which are wrong/serve no purpose. I also don't see, for example, --syn (a.k.a. --tcp-flags SYN,RST,ACK,FIN SYN) being used for new connections, which is a bit surprising to me. Possibly the state module is what takes care of some of this behind the scenes -- I don't know.

Edit: also, regarding the performance concern: sure, I could add --syn to the raw table rule, then (simplifying this greatly) the only performance hit would be on the if() statement that has to check every packet for specific TCP flags as well as an if() for the destination port number. That might save CPU time, depending on what the other processing is that goes on after that point.

Tested that theory (no performance tests though): yeah, using --syn works fine. So the ruleset:

tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
Thus, it's by default not just listening on the LAN interface, but *every* interface, including WAN. This is not good on a huge number of levels, but it is what it is...and thus, yes, the DROP is absolutely needed.

Click to expand...

I'm fairly certain the reason this binds to INADDR_ANY is because then you don't have to restart sshd when your WAN IP changes. If you explicitly tell sshd/dropbear (or any other daemon) to bind to a specific IP address, you have to restart the daemon -- it can't be done on-the-fly. Imagine you're SSH'd into your router (on the LAN) and suddenly your socket gets dropped for no reason. You SSH back in and things seem fine. What happened? Yeah, the first thing I'm going to think is "my WAN IP changed" -- not.

The same advice applies to all the other daemons, except for things which should truly be LAN-only (like Samba, etc.) -- and for WAN access to those, again, proper DNAT rules can solve those.

Basically, properly-written firewalling rules are how you deal with the INADDR_ANY situation. In fact, with some daemons/services (I'm looking at you rpcbind + NFS!), you must leave them bound to INADDR_ANY for proper functionality (especially in network environments where there's a public and a private network).

This is not correct. INPUT will only be traversed for any packets with a destination address of a local interface - otherwise, it will flow through FORWARD for LAN-destined packets that aren't the local machine. The DNAT is what makes it destined for the local LAN IP of the router in the first place, so unless you mangle with WANPREROUTING, the destination IP will be the WAN IP and thus cannot ever traverse INPUT (or FORWARD, for that matter).

Click to expand...

While I am always open to learn something new, I think I am correct here. I have tested it myself with my openvpn service that is running on my router. You should do your own test so you can convince yourself. I eliminated the PREROUTING rule that sends all WAN traffic to WANPREROUTING with this

. Then I ran a scan from GRC.COM on a tcp openvpn port. As I thought, the port was open and I 'failed'. Then I deleted my INPUT rule and ran the scan again and what do you know the port was 'stealth' and I passed.

Shouldn't you try to put that rule in the INPUT chain to follow the recommend convention?

Click to expand...

There is no INPUT chain in table raw, only PREROUTING and OUTPUT. And that rule cannot be moved into the filter table because it would block the -j DNAT'd traffic that we want to pass (as I stated here) -- the packet is already rewritten with a new destination port number by the time it gets to the table filter INPUT chain.

The first example is susceptible to the complexity I mentioned above, because of use of -d with the WAN IP.

I spent almost 2 hours digging through Tomato source last night trying to figure out exactly where to put these kind of rules (ones that rely on wan_ipaddr) and my opinion (based on the code) is that they go into WAN Up, not Firewall. However the code is such a complete utter mess that it's very difficult for me to tell with absolute certainty. There's all sorts of one-offs all over the place for adding rules via system("iptables", ...), and other places use code that populates rules into /etc/iptables. I also can't figure out how the rules are cleared; I'm thinking iptables-restore is what effectively does this, with the contents of /etc/iptables, but again I'm not absolutely certain.

However, guess what -- the 2nd example you give works great and makes perfect sense why. Here's what I used exactly:

1. The "!" (not) operator needs to be escaped if issued from a shell or something that calls system() (which uses /bin/sh), else the shell interprets the "!" itself
2. Removed the -t filter on the last rule (filter table is the default).
3. `nvram get lan_ipaddr` will return 192.168.1.1 normally (unless you've changed your routers' LAN IP address of course)

The reason this works is that the nat table WANPREROUTING chain DNAT rule rewrites both the destination IP and port number, before the packet makes it to the filter table INPUT chain. Therefore, in the INPUT chain, the idea is to key off of the destination IP being re-written to the router's LAN IP. Absolutely works.

I would highly recommend this method be used over my aforementioned method. These rules should go into the Script -> Firewall section, because they only need to be applied once and the IPs/details won't change. Thank you so much, Bird333. Perfect.

BTW (and this is mainly for gijs73), to remove the rules I proposed before, just issue the same rules but with -A turned into -D, i.e.:

I am holding off till we can settle on what is best. This is what I have placed in my firewall script for now. Also, I went ahead and just rebooted the router. Didn't want to risk leaving any trace of iptable changes that were wrong.

Tomato does use iptables-restore, because this needs a single call to the big userspace iptables from the rc c code. So the rules are first written to a temp file in the iptables export format then the file loaded.
I put 'logger' commands at top of firewall and wanup scripts to timestamp, they are run very close together (and quite often during boot and gui changes, even init can be re-run!), but firewall should be just before the wan is up, wan up just after, but I have a feeling they are almost coincident and I'm pretty sure tomato doesn't wait for your custom firewall rules to run before really running the wan up.

FWIW I prefer the $(nvram get lan_ipaddr) syntax, mainly because my eyes and monitors don't like the back tics, and only ever handle Linux!

The code I looked at did not indicate Scripts -> Firewall gets run on DHCP expiry or DHCP renegotiation (meaning, from what I saw, wan_ipaddr only gets updated prior to running Scripts -> WAN Up, not Firewall). I am not going to spend another 2-3 hours doing a full code analysis and documenting it here on a forum because of this (I started to yesterday but said f-it because it's a complete rat's nest). Those who are familiar with the code already need to step up to the plate and chime in or document it or whatever else. It just doesn't make sense for someone to have to reverse-engineer something that another is already familiar with.

I've read the most part of this thread and I thought it would solve my problems but I still can't use OpenVPN on port 53 UDP.
I'm using the latest Shibby on a rt-n66u and I have set up server 1 on port 123 UDP and then I've modified the iptables above but I still can't connect using port 53. Reading the logs, I see that the router receives the first packet (tls-auth) but then the client doesn't receive a response packet and the connection resets. If I connect to port 123 UDP everything works as expected.

Exactly. I'm home now and I can connect using port 53 from inside my lan, but I can't from the outside. I've tried some of the iptable rules from the other thread but I get an error when trying to connect from the outside. Have you found the definitive iptable rules to route all the traffic from wan port 53 to the router port 1194 and be able to connect from the outside with port 53? I really don't care about connecting from the inside.
Thanks!

I realize this an extremely old post, but in case anyone is monitoring, i will take my chances. I have an open vpn server which works great on port 1194. Sometimes the only ports not blocked are udp53 so I would like to configure the setup to use port 53 for the VPN. I can't make the router E4200 v1 running tomato 1.28 use port 53 for the VPN server so I am trying to forward the request coming in from the client on port 53 to port 1194 (UDP). The sucker gets close, appears authenticate and then just hangs. I check the log and get the the following error that the negotiation did not occur in time , tls error, blah blah.
Any pointers on what I might be doing wrong?