Why WebProxy requests don't hit dst-nat ?

I followed this article:

http://wiki.mikrotik.com/wiki/Multiple_Web_Servers

And redirection between physical machines works fine.

However I’m also running multiple servers on single machine. I know I could use some nginx or other server side software but I think it should be possible to accomplish this using router and dst-nat only.

So I added following domains to DNS:

add address=192.168.2.4 name=nuc.bestponyf.ml
add address=192.168.10.80 name=wubz.bestponyf.ml
add address=192.168.10.90 name=recordings.bestponyf.ml

Where 192.168.10.0/24 is non-existing virtual network just for NAT purpose
And following entries to NAT:

add chain=dstnat dst-address=192.168.10.90 protocol=tcp dst-port=80\
action=dst-nat to-addresses=192.168.2.4 to-ports=8190
add chain=dstnat dst-address=192.168.10.80 protocol=tcp dst-port=80\
action=dst-nat to-addresses=192.168.2.4 to-ports=8180

However it totally doesn’t work. NAT rules don’t even show any counters - nothing hits those rules and WebProxy returns gateway timeout. In /ip firewall connections i can see connections with dst-address 192.168.10.90 or 80 but ofc there’s no response. Manual requests to 192.168.10.90 from LAN work as expected.

I tried to add this network to interface of .2.0/24 but it didn’t help much. I don’t think it should be necessary either

add address=192.168.10.1/24 interface=br-extern network=192.168.10.0

What I actually did manage to do was to capture WebProxy requests with src-nat (counters and logs recorded packets from WebProxy IP to .10.90/80 (only after adding .10.0/24 address to interface). But It doesn’t allow to redirect so I don’t think it’s useful.

It will werk if you add those ‘non excisting’ IP adresses to a new bridge.
Call this bridge something like nat-bridge or nything you like.
Then add those 2 addresses 192.168.10.80/24 and .90/24 to this bridge.

That will do the job.

Add addresses as in - add as router IPs? in /ip addresses?

EDIT:

So now i have:

add address=192.168.2.4 name=nuc.bestponyf.ml
add address=192.168.10.80 name=wubz.bestponyf.ml
add address=192.168.10.90 name=recordings.bestponyf.ml



add address=192.168.0.2/24 interface=ether1-gateway network=192.168.0.0
add address=192.168.2.1/24 interface=br-extern network=192.168.2.0
add address=192.168.10.90/24 interface=br-virtual network=192.168.10.0
add address=192.168.10.80/24 interface=br-virtual network=192.168.10.0

(br-virtual with no attached physical interfaces)

add action=dst-nat chain=dstnat comment="virtual IPs" dst-address=192.168.10.80 dst-port=80 log=yes protocol=tcp to-addresses=192.168.2.4 to-ports=8180
add action=dst-nat chain=dstnat dst-address=192.168.10.90 dst-port=80 log=yes protocol=tcp to-addresses=192.168.2.4 to-ports=8190

Yet still:

wget --no-proxy 'wubz.bestponyf.ml'
--2016-04-18 20:09:05--  http://wubz.bestponyf.ml/
Resolving wubz.bestponyf.ml (wubz.bestponyf.ml)... 89.72.64.207
Connecting to wubz.bestponyf.ml (wubz.bestponyf.ml)|89.72.64.207|:80... connected.
HTTP request sent, awaiting response... 504 Gateway Timeout
2016-04-18 20:09:06 ERROR 504: Gateway Timeout.

Out of curiosity - do the client devices use the Mikrotik as their DNS server? If not, then they’re just not getting the right IP address.

Open a command prompt on a client machine and try to ping something by name - e.g. ping wubz.bestponyf.ml
and see what IP address it resolves to.

Either assign the Mikrotik as the DNS server in your DHCP scope, or else make a dstnat chain rule for udp:53 with action=redirect

Side note - if you’re using DNS proxy and have allow remote requests=yes, then double check to be sure that your router doesn’t respond to DNS queries from the WAN side or else you’re going to get pressed into service as a DDoS warrior. :wink:

No, DNS server is just for WebProxy itself. DNS is resolved on clients to external router address (89.72.64.207, i do have all those subdomains registered in domain provider service). This webproxy is meant for outside traffic not inner one. All of clients (non-DHCP ones) use 8.8.8.8 including server itself. I’m not really going to rely on router DNS server.

It should more or less work like this:
client resolves DNS of all addresses to 89.72.64.207 (my public, static IP)
if it comes from LAN, then packets go to ISP gateway and are rerouted back to my router if not then just comes from outside
my router dst-nat redirects port 80 to 8080, where it’s handled by /ip WebProxy
WebProxy resolves domain name using router static DNS and sends request to final server (192.168.10.90)
now dst-nat should translate 192.168.10.90:80 to 192.168.2.4:8190 but it doesn’t. It looks like WebProxy just shots through dst-nat and sends request to 192.168.10.90:80.

So no I’m not using DNS server on client machines but I don’t think it has anything to do with that after all I want it to work from the outside.

EDIT:

I’ve just tested it with actual request from the outside (3g) and it also receives gateway timeout

You can’t use dstnat to map hostnames to internal servers. NAT is only aware of IP addresses and TCP/UDP port numbers.
The Mikrotik never uses DNS when building connections through the firewall, and the client has already done the DNS lookup on their end - so all the Mikrotik firewall ever sees is this:

1.2.3.4/TCP/12011 → 89.72.64.207:80

The dstnat rule will map this to whatever rule matches, but it has no idea how the client got that IP - host name doesn’t come back into the picture with HTTP until after the TCP socket establishes, when the client says to the server: “hey, I’d like wubz.bestponyf.ml”

You could set up the WEB proxy feature (but be VERY careful because if you allow any URL, then the worms will find you and list you as an open http proxy, after which, your box WILL be used to anonymize other people’s web surfing for them, and use your bandwidth to do it).

The web proxy WILL do a dns lookup on the URL, so this will trigger your given dstnat rules as the Mikrotik itself tries to establish the proxy connection.

Configuring the proxy rules like this should work:
/ip proxy access
add dst-address=192.168.10.0/24
add action=deny

You’ll also need to set the proxy to listen on your WAN IP at port 80.

Again - BE VERY CAREFUL WITH REVERSE PROXY - after you set it up, be sure to go out on the Internet somewhere and configure a browser to use your Mikrotik as a proxy to be sure that it rejects everything except your internal sites - also try setting some test site’s IP address in the hosts file of the remote test machine to be your Mikrotik’s IP (remove the proxy settings) - browsing to that test site should go to your Mikrotik and get a rejection as well. If you can browse arbitrary web sites from your Mikrotik’s proxy, then that’s very bad.

But i DO use web proxy ._.

I’m not sure if my explanation was too chaotic but I even gave link to tutorial explaining how to set up hostname based routing using web proxy.

My actual problem is that whereas it does work with routing between PCs (i have suse.bestponyf.ml, phone.bestponyf.ml, nuc.bestponyf.ml… and so on corresponding to various physical machines with various physical addresses and this DOES work. I’d also like to have something like someservicename.bestponyf.ml which would use 192.168.2.4 (just like nuc.bestponyf.ml) but not on port :80 but port 8180.

So atm I have something like this:
nuc.bestponyf.ml:80 → 192.168.2.4:80
suse.bestponyf.ml:80 → 192.168.1.3:80
phone.bestponyf.ml:80 → 192.168.4.9:80
… few more here

And it does work

I’d like to have also something like that:

wubz.bestponyf.ml → 192.168.2.4:8180

I thought that simple way to do this would be to use dst-nat like this:
wubz.bestponyf.ml → 192.168.10.80:80

and then dst-nat 192.168.10.80:80 to 192.168.2.4:8180

but requests created BY web proxy don’t go through dst-nat I think. They go directly to 192.168.10.80 and then time out because there’s no such IP in the network

According to the Packet flow diagram, you’re correct.

IP output goes to routing decision, followed by the “output” block:
bridge decision → connection tracking → mangle output → filter output → routing adjustment

then to the postrouting block:
mangle postrouting → src-nat → hotspot-out → HTB Global → Simple Queues

No dstnat in this chain of events.

For any host that requires a “portmap” you could try setting up a deny rule in the proxy access table, but one that redirects to the same URL:8010 where you have a regular direct NAT pinhole from the outside…

I’m not sure if I understand this part. You say that I should deny “wubz.bestponyf.ml” in WebProxy ACL and in case someone requests it redirect him directly to 89.72.64.207:8190 which would be handled by regular NAT?

specifically this part:

and in case someone requests it redirect him

Is it even possible?

Oh yeah, it is possible thanks a lot, it works :slight_smile:

wubz.bestponyf.ml action=deny, redirect-to=nuc.bestponyf.ml:8180

A bit glitchy because paths are not preserved so any path redirects just to root and url in browser is not preserved as well but if i’d be looking for perfect solution I’d probably use nginx or something on server itself. This is more like proof of concept that it is possible to actually do it using only a router with ROS. Nice.

I took a cursory peek at the docs to see whether a regex match could be used in the redirect-to URL, but nothing seems to indicate that this is doable.
(It talks about using regex in the dst-host field, but no mention of including tokens from regex in the redirected URL)

I figured this behavior would be the case, but at least it connects you to the site to begin with and after that, as long as the site uses relative references, everything should work properly.