Firewall and port forwarding

This seems pretty simplistic, but I’m coming from a PIX, and I’m just not able to wrap my head around it.

I’ve got a new RB750G sitting behind a cable modem. I want to accept SSH on a non-standard port and forward this to port 22 of a device on my local LAN. So far, I haven’t tweaked much of anything except to configure things for my internal IP range. The default 3 filter rules are still in place. I’ve run port scans and this seems like it leaves things fairly tightly locked down. I have successfully opened a hole to allow SSH to the RB, but I can’t seem to open a hole for port 12345 and pass this to 192.168.0.30 port 12345. I’ve tried couple different firewall filter/firewall nat rules and none of them seem to work. I’m assuming that I am confused on the packet path. Seems like:

/ip firewall filter
add chain=forward action=accept protocol=tcp dst-port=12345

and

/ip firewall nat
add chain=dstnat action=dst-nat to-addresses=192.168.0.30 to-ports=22 protocol=tcp in-interface=ether1-gateway dst-port=12345

would work, but when I try and connect it never even hits the filter rule for some reason. I’ve searched and read, and it all seems to make sense, but when I try and translate for my particular case it doesn’t seem to work.

Try changing that filter rule to chain=input. I think at this point, the router may still think the request is for it (input) rather than a device behind it (forward). No dsnat applied yet.

‘input’ and ‘forward’ are parallel - a packet is in one or the other after prerouting NAT decides the final destination address of the packet.

Post the info requested in my signature.

No luck. I've tried most of the combinations that I could think of, like changing the dst-port to 22 in case the NAT was taking place before the filtering and changing the chain. Watching the activity graphs last night in Winbox it almost seemed to be getting around the filter rules entirely and seemed to be hitting the dst-nat rule while also incrementing the "chain=input action=drop in-interface=ether1-gateway" rule. I have made sure that the accept rules I am adding are above this final drop, but I don't think that I have managed to hit any of the rules yet. Here are the specs you requested:

/ip address print detail
Flags: X - disabled, I - invalid, D - dynamic
0 ;;; default configuration
address=192.168.0.1/24 network=192.168.0.0 broadcast=192.168.0.255 interface=ether2-local-master actual-interface=ether2-local-master

1 D address=67.172.215.XXX/22 network=67.172.212.0 broadcast=67.172.215.255 interface=ether1-gateway actual-interface=ether1-gateway

/ip route print detail
Flags: X - disabled, A - active, D - dynamic, C - connect, S - static, r - rip, b - bgp, o - ospf, m - mme, B - blackhole, U - unreachable, P - prohibit
0 ADS dst-address=0.0.0.0/0 gateway=67.172.212.1 gateway-status=67.172.212.1 reachable ether1-gateway distance=1 scope=30 target-scope=10

1 ADC dst-address=67.172.212.0/22 pref-src=67.172.215.XXX gateway=ether1-gateway gateway-status=ether1-gateway reachable distance=0 scope=10

2 ADC dst-address=192.168.0.0/24 pref-src=192.168.0.1 gateway=ether2-local-master gateway-status=ether2-local-master reachable distance=0 scope=10

/interface print
Flags: D - dynamic, X - disabled, R - running, S - slave

NAME TYPE MTU L2MTU

0 R ether1-gateway ether 1500 1524
1 R ether2-local-master ether 1500 1524
2 R ether3-local-slave ether 1500 1524
3 R ether4-local-slave ether 1500 1524
4 ether5-local-slave

/ip firewall export

jan/05/2011 09:17:33 by RouterOS 4.11

software id = 1Y5T-7BI4

/ip firewall connection tracking
set enabled=yes generic-timeout=10m icmp-timeout=10s tcp-close-timeout=10s tcp-close-wait-timeout=10s tcp-established-timeout=1d tcp-fin-wait-timeout=10s tcp-last-ack-timeout=10s
tcp-syn-received-timeout=5s tcp-syn-sent-timeout=5s tcp-syncookie=no tcp-time-wait-timeout=10s udp-stream-timeout=3m udp-timeout=10s
/ip firewall filter
add action=accept chain=input comment="default configuration" disabled=no protocol=icmp
add action=accept chain=input comment="default configuration" connection-state=established disabled=no in-interface=ether1-gateway
add action=accept chain=input comment="default configuration" connection-state=related disabled=no in-interface=ether1-gateway
add action=accept chain=input comment="" disabled=no dst-port=15610 protocol=tcp
add action=accept chain=input comment="" disabled=no dst-port=22 protocol=tcp src-address=216.30.183.248
add action=drop chain=input comment="" disabled=no in-interface=ether1-gateway
/ip firewall nat
add action=masquerade chain=srcnat comment="default configuration" disabled=no out-interface=ether1-gateway
add action=dst-nat chain=dstnat comment="" disabled=no dst-port=15610 in-interface=ether1-gateway protocol=tcp to-addresses=192.168.0.30 to-ports=22
/ip firewall service-port
set ftp disabled=no ports=21
set tftp disabled=no ports=69
set irc disabled=no ports=6667
set h323 disabled=no
set sip disabled=no ports=5060,5061
set pptp disabled=no

That correctly forwards tcp/15610 to tcp/22 on 192.168.0.30. There is nothing blocking traffic to .30, or its reply packets.

You either have an ISP dropping the traffic for you, a bad default gateway on .30, or a host firewall on .30. The router is configured correctly.

@fewi: Thanks! That always gets me thinking. :smiley:

I did a test with the firewall rule and using action=add-src-to-address-list. I used port 8080 dstnated to an internal address on port 80. If you use the “chain=forward” filter rule, you must use the final dst-port in the rule. In my case, it was “dst-port=80” (not 8080). In your case, it should be “dst-port=22” (not 12345). Port 8080 (external port) did not end up in the address list, but port 80 did, even tho I used port 8080 on the request.

I think I found it. If you use that one dstnat, you need a srcnat to switch the ports back on the reply. Sometimes the obvious misses me. :blush:

/ip firewall nat
add chain=dstnat action=dst-nat dst-address=xx.xx.xx.xx to-addresses=192.168.0.30 to-ports=22 protocol=tcp dst-port=12345

add chain=srcnat action=src-nat to-addresses=xx.xx.xx.xx to-ports=12345 src-port=22 protocol=tcp src-address=192.168.0.30

Destination NAT is automatically undone as source NAT for reply packets, and vice versa. After all, you don’t need to destination NAT something just because you have a masquerade rule.

I’m pretty sure the router is configured right and the problem is either with the ISP, or either host, or a firewall in the middle (not the router) blocking traffic.

But, regardless of whether the destination machine is configured correctly, wouldn’t this increment the counters on the filter rule? I don’t believe this is the ISP dropping traffic as it’s only been broken since I swapped the RB750G for my old PIX 501 where it was working perfectly. I copied the rules to map a different port to a different machine on my inside LAN and this doesn’t work either. The counters on both of these rules is still zero across the board. The counters for the NAT rules are actually getting incremented when I try and connect.

The rules you showed aren’t incrementing because they’re in the wrong chain.

Remove these:

add action=accept chain=input comment="" disabled=no dst-port=15610 protocol=tcp
add action=accept chain=input comment="" disabled=no dst-port=22 protocol=tcp src-address=216.30.183.248

And replace it with - this is unneeded, but at least you’ll see counters incrementing - the following:

/ip firewall filter
add action=accept chain=forward disabled=no dst-port=22 protocol=tcp dst-address=192.168.0.30

to count the packets after NAT going to the internal host. You can also count the packets before NAT:

/ip firewall filter
add action=accept chain=prerouting dst-address-type=local in-interface=ether1-gateway protocol=tcp dst-port=15610

But again, neither rule is needed. By default traffic is accepted (PIX equivalent is an ACL with an implicit “permit ip any any” implicitly applied as an access-group), all your filter rules are in the ‘input’ chain which is only used for traffic destined TO the router (not THROUGH the router) AFTER any destination NAT. The traffic you’re causing with SSH to a host behind the router would never be in the ‘input’ chain.

Ok, I was able to see the accept filter rules increment after making the changes you suggested, and I understand that there are no rules applying to the forward chain, so it is open by default. But, there is no other firewall in between the RB750G and the device, the device is hanging off of port 2 of the RB. While it is possible, I find it highly unlikely that Comcast picked the exact moment I switched firewalls to start blocking random traffic. I can’t confirm it, since I can’t get to it, but I think the device is configured with the proper netmask and default gateway. When I had things working with the PIX, the ports I was forwarding showed up as open or filtered when running a port scanner from the internet against my public IP address, with the RB750G this doesn’t seem to be the case or there is some other simple setting that I have configured incorrectly. I saw that there was a “Protect LAN” checkbox in the web interface at one point, and it was unchecked, but what does this correspond to in the CLI? Can you tell me how to dump traffic so that I can see where the communication is stopping?

You can use the traffic-monitor and sniffer in the /tool menu to watch traffic.

I really think the host you’re trying to get to is misconfigured. Wrong default route, maybe. Or a static ARP entry for the default gateway IP - the MAC address mapped to that IP changed when you replaced the router.

Off topic re: karma PM: thanks for the kind words, Tim.

Thank you both for your help, the problem actually seemed to be the cable modem itself. I just happened to be messing with it and saw that it’s uptime was way shorter than it should have been, after watching for awhile I realized it was regularly rebooting. After replacing it everything works.

On a somewhat related note, is there a set of baseline firewall filters that you recommend for something attached to the public internet? I don’t have much open, so I would think I was fairly secure with the default deny on the input and forward chains, but I’m not sure.

I’m a simple guy, I use the below. It assumes an address list named “Administrative_Networks” that get full access to the router - the address list could be made up of network addresses, or host addresses. It also assumes the WAN interface is called ‘outside’. The sample rule set shows:

  • how to make the firewall stateful by accepting relating and established service early so that the firewall has to do as little work as possible
  • how to change the default policy from default permit (blacklist) to default deny (whitelist) - at the end of each chain everything that hasn’t been accepted yet is dropped. It’s easier to define what you want that it is to define what you don’t want
  • how to protect router services themselves. Open up ports in the input chain to provide services running directly on the router to users. I run only DNS, NTP, and DHCP on the server. DHCP actually cannot be firewalled on RouterOS as the DHCP daemon listens for raw packets before the IP firewall comes into play, but I like to list the port anyway to explicitly show that DHCP is permitted.
  • how to punch holes for traffic through the firewall, SSH is permitted to 192.168.1.10 (has to go with a destination NAT rule to forward ports)
  • how to protect LANs behind the router from one another, each LAN can only talk to the WAN, LANs cannot pass traffic between each other. An exception is made for interface inside1 talking to inside2
  • how to prevent LAN users from passing certain traffic to the WAN, though all other such traffic is later allowed. This makes the router behave like other home routers where the traffic initiated on the LAN is generally deemed safe

I’m overexplaining all that in case others read it. This ruleset might not be adequate for a service provider. It is, however, simple and easy to understand. There are very many posts on these forums from users with long, complicated rulesets pasted together from different sources. A firewall ruleset that requires more than 20 rules to process a packet and that you don’t understand completely so you can determine why traffic isn’t flowing like you want it to is - in my opinion - ultimately a badly designed one.

/ip firewall filter
add action=accept chain=input comment="allow established" connection-state=established
add action=accept chain=input comment="allow related" connection-state=related
add action=drop chain=input comment="drop invalid" connection-state=invalid
add action=accept chain=input comment="allow local service UDP ports from LAN" disabled=no dst-port=53,67,123 in-interface=!outside protocol=udp
add action=accept chain=input comment="allow local service TCP ports from LAN" disabled=no dst-port=53 in-interface=!outside protocol=tcp
add action=accept chain=input comment="allow rate-limited ICMP" disabled=no limit=20,20 protocol=icmp
add action=accept chain=input comment="allow everything from admin networks" disabled=no src-address-list=Administrative_Networks
add action=drop chain=input comment="drop everything else" 
add action=accept chain=forward comment="forward established traffic" connection-state=established 
add action=accept chain=forward comment="forward related traffic" connection-state=related
add action=drop chain=forward comment="drop invalid" connection-state=invalid
add action=accept chain=forward comment="allow SSH to 192.168.1.10 (IP after destination NAT port forwarding)" dst-address=192.168.1.10 dst-port=22 protocol=tcp
add action=drop chain=forward comment="drop undesired TCP" disabled=no dst-port=135-139,445,1434,4444 protocol=tcp
add action=drop chain=forward comment="drop undesired UDP" disabled=no dst-port=135-139,445,1434,4444 protocol=udp
add action=accept chain=forward comment="forward traffic from customer interfaces to WAN (all other networks cannot talk to one another)" out-interface=outside
add action=accept chain=forward comment="forward traffic from inside1 to inside2, return traffic is stateful, inside2 cannot initiate traffic to inside1 and can only reply" in-interface=inside1 out-interface=inside2
add action=drop chain=forward comment="drop everything else"

I know that this is and old post but google point me to here, it’s very usefull and it work for me.
The only think that i can add is that, in my case, was not necessary the “/ip firewall filter” rule because my default configuration on the rb2011uias has a rule that not drop packages that got to dsnated chain.

this is the rule:

/ip firewall filter add chain=forward action=drop connection-state=new connection-nat-state=!dstnat

I dont like that rule diego, using ! is kewl but often has other consequences which trip you up later.
It is the default rule in place but I prefer simply
allow connection-state=dstnat in my forward chain.
It basically says allow all port forwarding through the firewall that you have identified in the /ip firewall NAT section.


Now the interesting thing about the NAT rules section,
If you do not limit the NAT rule by source address in the Dst NAt rule, the port appears closed (ie its visible) when scanning the router.
If you put in a source address or list in the Dst NAt rule, the port is invisible when the router is scanned.

This shouldn’t be a surprise. If you don’t limit access to such port on firewall on L3 or L4 (IP or TCP/UDP), but rather on some application level, then firewall has no idea about it (FW works on L4) and keeps port active. Only the app, listening to that port, then decides to grant access or deny it. For port scanners, which don’t get to this stage, port is available for connections.

Thanks for the confirmation Chief!
It was a pleasant surprize when using grc to scan myself LOL