NGINX Proxy Manager & RouterOS

I’ve migrated from a USG router to the Mikrotik. I have most things working except I’ve lost the ability to access internal hosts that are behind my nginx-proxy-manager container which resides on a server.

The gnix-proxy-managers works in that I can request new and renew certs without any issue. Access from the interwebs to my sites works fine. Internally I’ve had a few different results depending on what I was fiddling with at the time, but never had success. The connection times out, or is rejected, or I have sometimes ended up at the RouterOS web page despite trying to reach a different server. Using the direct IP:Port# works internally.

I tried DNS rewrite rules on my DNS (Adguard Home) but that didn’t work either. A Hairpin NAT rule might be needed but the one I tried didn’t work. I was expecting it just to work, as it did with the USG, without needing to do extra work, but that was a wrong assumption. I’ve read multiple posts and guides on Hairpin NAT over the last couple of weeks but it keeps confusing me as my grasp of network basics doesn’t extend that far. Config attached, any pointers would be appreciated.

/interface bridge
add comment=10.0.0.1 name=BR1 protocol-mode=none vlan-filtering=yes
/interface ethernet
set [ find default-name=ether3 ] comment="TRUNK - All VLAN"
set [ find default-name=ether4 ] comment="Access Port - VL110"
set [ find default-name=ether5 ] comment="MGMT Port" name=ether5-mgmt
set [ find default-name=ether1 ] comment="WAN1 Port" l2mtu=1586 mtu=1586 \
    name=wan1
set [ find default-name=ether2 ] comment="WAN2 Port" disabled=yes l2mtu=1586 \
    mtu=1586 name=wan2
/interface vlan
add comment=INFRA disabled=yes interface=BR1 name=VL100-INFRA vlan-id=100
add comment=RaD interface=BR1 name=VL110-RaD vlan-id=110
add comment=KaL interface=BR1 name=VL120-KaL vlan-id=120
add comment=IoT interface=BR1 name=VL130-IoT vlan-id=130
add comment=Docker interface=BR1 name=VL140-DOCK vlan-id=140
add comment=Work interface=BR1 name=VL150-WORK vlan-id=150
add comment=Guest interface=BR1 name=VL190-GUEST vlan-id=190
add comment=MGMT interface=BR1 name=VL1010-MGMT vlan-id=1000
/interface list
add comment=defconf name=WAN
add comment=defconf name=LAN
add name=VLAN
add name=MGMT
/ip pool
add comment=RaD name=VL110-POOL ranges=10.10.1.10-10.10.1.254
add comment=KaL name=VL120-POOL ranges=10.10.2.10-10.10.2.254
add comment=IoT name=VL130-POOL ranges=10.10.3.10-10.10.3.254
add comment=Docker name=VL140-POOL ranges=10.10.4.135-10.10.4.254
add comment=WORK name=VL150-POOL ranges=10.10.5.10-10.10.5.254
add comment=GUEST name=VL190-POOL ranges=10.10.9.10-10.10.9.254
add comment=MGMT name=VL1010-POOL ranges=10.10.10.100-10.10.10.254
add comment=ACCESS name=ether5-POOL ranges=10.1.1.10-10.1.1.254
add comment=LAN name=LAN-POOL ranges=10.0.0.100-10.0.0.254
/ip dhcp-server
add address-pool=VL110-POOL comment=10.10.1.0 interface=VL110-RaD name=\
    VL110-DHCP
add address-pool=VL120-POOL comment=10.10.2.0 interface=VL120-KaL name=\
    VL120-DHCP
add address-pool=VL130-POOL comment=10.10.3.0 interface=VL130-IoT name=\
    VL130-DHCP
add address-pool=VL140-POOL comment=10.10.4.0 interface=VL140-DOCK name=\
    VL140-DHCP
add address-pool=VL150-POOL comment=10.10.5.0 interface=VL150-WORK name=\
    VL150-DHCP
add address-pool=VL190-POOL comment=10.10.9.0 interface=VL190-GUEST name=\
    VL190-DHCP
add address-pool=VL1010-POOL comment=10.0.0.0 interface=VL1010-MGMT name=\
    VL1010-POOL
add address-pool=ether5-POOL comment=10.1.1.0 interface=ether5-mgmt name=\
    ether5-DHCP
add address-pool=VL100-POOL comment=10.0.0.0 interface=BR1 name=LAN-DHCP
/queue interface
set ether3 queue=ethernet-default
/routing table
add disabled=no fib name=useWAN2
/system logging action
set 1 disk-file-count=10 disk-lines-per-file=4096
/interface bridge port
add bridge=BR1 frame-types=admit-only-untagged-and-priority-tagged interface=\
    ether4 pvid=110
add bridge=BR1 interface=ether3
add bridge=BR1 interface=wifi-rad-5 pvid=1000
add bridge=BR1 interface=wifi-rad-2 pvid=1000
/ip neighbor discovery-settings
set discover-interface-list=VLAN
/interface bridge vlan
add bridge=BR1 tagged=BR1,ether3 vlan-ids=100
add bridge=BR1 tagged=BR1,ether3 untagged=ether4 vlan-ids=110
add bridge=BR1 tagged=BR1,ether3 vlan-ids=120
add bridge=BR1 tagged=BR1,ether3 vlan-ids=130
add bridge=BR1 tagged=BR1,ether3 vlan-ids=140
add bridge=BR1 tagged=BR1,ether3 vlan-ids=150
add bridge=BR1 tagged=BR1,ether3 vlan-ids=190
add bridge=BR1 tagged=BR1,ether3 vlan-ids=1010
add bridge=BR1 tagged=BR1,ether3 vlan-ids=1000
/interface list member
add interface=VL150-WORK list=MGMT
add interface=VL110-RaD list=MGMT
add interface=VL1010-MGMT list=MGMT
add interface=ether5-mgmt list=MGMT
add interface=wan1 list=WAN
add interface=VL110-RaD list=VLAN
add interface=VL120-KaL list=VLAN
add interface=VL130-IoT list=VLAN
add interface=VL140-DOCK list=VLAN
add interface=VL150-WORK list=VLAN
add interface=VL190-GUEST list=VLAN
add interface=VL1010-MGMT list=VLAN
add interface=VL100-INFRA list=LAN
add interface=VL110-RaD list=LAN
add interface=VL120-KaL list=LAN
add interface=VL130-IoT list=LAN
add interface=VL140-DOCK list=LAN
add interface=VL150-WORK list=LAN
add interface=VL190-GUEST list=LAN
add interface=VL1010-MGMT list=LAN
add interface=wan2 list=WAN
add interface=BR1 list=LAN
/ip address
add address=10.1.1.1/24 interface=ether5-mgmt network=10.1.1.0
add address=10.10.1.1/24 interface=VL110-RaD network=10.10.1.0
add address=10.10.2.1/24 interface=VL120-KaL network=10.10.2.0
add address=10.10.3.1/24 interface=VL130-IoT network=10.10.3.0
add address=10.10.4.1/24 interface=VL140-DOCK network=10.10.4.0
add address=10.10.5.1/24 interface=VL150-WORK network=10.10.5.0
add address=10.10.9.1/24 interface=VL190-GUEST network=10.10.9.0
add address=10.10.10.1/24 interface=VL1010-MGMT network=10.10.10.0
add address=10.10.0.1/24 interface=BR1 network=10.10.0.0
/ip cloud
set update-time=no
/ip dhcp-client
add interface=wan1
add interface=wan2
/ip dhcp-server network
add address=10.0.0.0/24 domain=rdkl.lan gateway=10.0.0.1
add address=10.1.1.0/24 comment=access domain=rdkl.lan gateway=10.1.1.1
add address=10.10.0.0/24 comment=infra dns-server=10.10.0.5,10.10.0.7 domain=\
    rdkl.me gateway=10.10.0.1
add address=10.10.1.0/24 comment=rad dns-server=10.10.0.5,10.10.0.7 domain=\
    rdkl.me gateway=10.10.1.1
add address=10.10.2.0/24 comment=kal dns-server=10.10.0.5,10.10.0.7 domain=\
    rdkl.me gateway=10.10.2.1
add address=10.10.3.0/24 comment=iot dns-server=10.10.0.7,10.10.0.5 domain=\
    rdkl.me gateway=10.10.3.1
add address=10.10.4.0/24 comment=dock dns-server=10.10.0.7,10.10.0.5 domain=\
    rdkl.me gateway=10.10.4.1
add address=10.10.5.0/24 comment=work dns-server=8.8.8.8,1.1.1.1 domain=\
    rdkl.lan gateway=10.10.5.1
add address=10.10.9.0/24 comment=guest dns-server=10.10.0.5,10.10.0.7 domain=\
    rdkl.me gateway=10.10.9.1
add address=10.10.10.0/24 comment=mgmt dns-server=10.10.0.5,10.10.0.7 domain=\
    rdkl.me gateway=10.10.10.1
/ip dns
set allow-remote-requests=yes servers=10.10.0.5,10.10.0.7
/ip dns static
add address=8.8.8.8 comment=defconf name=router.lan
/ip firewall filter
add action=accept chain=input comment="Allow Established,Related,Untracked" \
    connection-state=established,related,untracked
add action=drop chain=input comment="DROP - Invalid" connection-state=invalid
add action=accept chain=input comment="Allow ICMP" protocol=icmp
add action=accept chain=input comment="Allow Local Loopback" dst-address=\
    127.0.0.1
add action=accept chain=input comment="Allow LAN DNS queries-UDP" dst-port=53 \
    in-interface-list=LAN protocol=udp
add action=accept chain=input comment="Allow LAN DNS queries - TCP" dst-port=\
    53 in-interface-list=LAN protocol=tcp
add action=accept chain=input comment="Allow Winbox & SSH" dst-port=8291,22 \
    protocol=tcp src-port=8291,22
add action=accept chain=input comment=\
    "** Winbox Access (Full access to Router)" in-interface=ether5-mgmt
add action=accept chain=input comment=\
    "** Winbox Access (Full access to Router)" in-interface-list=MGMT
add action=drop chain=input comment=DROP
add action=fasttrack-connection chain=forward comment=FastTrack \
    connection-state=established,related hw-offload=yes
add action=accept chain=forward comment="Allow Established,Related,Untracked" \
    connection-state=established,related,untracked
add action=drop chain=forward comment="DROP - Invalid" connection-state=\
    invalid
add action=accept chain=forward comment="Allow IPSec policy - IN" \
    ipsec-policy=in,ipsec
add action=accept chain=forward comment="Allow IPSec policy - OUT" \
    ipsec-policy=out,ipsec
add action=accept chain=forward comment="ALLOW - Internet Traffic" \
    in-interface-list=LAN out-interface-list=WAN
add action=accept chain=forward comment="ALLOW - Port Forwarding" \
    connection-nat-state=dstnat
add action=accept chain=forward comment="ALLOW - VLAN inter-VLAN routing" \
    connection-state=new in-interface-list=LAN
add action=accept chain=forward comment="Accept all that is DST NATed" \
    connection-nat-state=dstnat connection-state=new
add action=drop chain=forward comment="DROP - All from WAN not DSTNATed" \
    connection-nat-state=!dstnat connection-state=new in-interface-list=WAN
add action=drop chain=forward comment=DROP
/ip firewall nat
add action=masquerade chain=srcnat comment="defconf: masquerade" \
    ipsec-policy=out,none out-interface=wan1
add action=masquerade chain=srcnat comment="defconf: masquerade" \
    ipsec-policy=out,none out-interface=wan2
add action=masquerade chain=srcnat comment="Hairpin attempt - failed" dst-address=\
    10.0.0.0/20 dst-address-type=!local protocol=tcp src-address=10.0.0.0/20 \
    src-address-type=!local
add action=dst-nat chain=dstnat comment="NGINX 80 - 80" dst-port=80 \
    in-interface=wan1 log-prefix="NGNIX 80" protocol=tcp to-addresses=\
    10.10.4.10 to-ports=80
add action=dst-nat chain=dstnat dst-port=80 in-interface=wan1 protocol=udp \
    to-addresses=10.10.4.10 to-ports=80
add action=dst-nat chain=dstnat comment="NGINX 443 - 80" dst-port=443 \
    in-interface=wan1 protocol=tcp to-addresses=10.10.4.10 to-ports=443
add action=dst-nat chain=dstnat dst-port=443 in-interface=wan1 protocol=udp \
    to-addresses=10.10.4.10 to-ports=443
add action=dst-nat chain=dstnat comment=JF-HTTP dst-port=8096 in-interface=\
    wan1 protocol=tcp to-addresses=10.10.4.40 to-ports=8096
add action=dst-nat chain=dstnat dst-port=8096 in-interface=wan1 protocol=udp \
    to-addresses=10.10.4.40 to-ports=8096
add action=dst-nat chain=dstnat comment=JF-HTTPS dst-port=8920 in-interface=\
    wan1 protocol=tcp to-addresses=10.10.4.40 to-ports=8920
add action=dst-nat chain=dstnat dst-port=8920 in-interface=wan1 protocol=udp \
    to-addresses=10.10.4.40 to-ports=8920
/ip service
set www port=8080
/ip traffic-flow
set interfaces=VL140-DOCK
/ip upnp
set enabled=yes
/ip upnp interfaces
add interface=BR1 type=internal
add interface=wan1 type=external
add interface=wan2 type=external
/ipv6 firewall filter
add action=accept chain=input comment=\
    "defconf: accept established,related,untracked" connection-state=\
    established,related,untracked
add action=drop chain=input comment="defconf: drop invalid" connection-state=\
    invalid
add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\
    icmpv6
add action=accept chain=input comment="defconf: accept UDP traceroute" port=\
    33434-33534 protocol=udp
add action=accept chain=input comment=\
    "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\
    udp src-address=fe80::/10
add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \
    protocol=udp
add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\
    ipsec-ah
add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\
    ipsec-esp
add action=accept chain=input comment=\
    "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
add action=drop chain=input comment=\
    "defconf: drop everything else not coming from LAN" in-interface-list=\
    !LAN
add action=accept chain=forward comment=\
    "defconf: accept established,related,untracked" connection-state=\
    established,related,untracked
add action=drop chain=forward comment="defconf: drop invalid" \
    connection-state=invalid
add action=drop chain=forward comment=\
    "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6
add action=drop chain=forward comment=\
    "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6
add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \
    hop-limit=equal:1 protocol=icmpv6
add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\
    icmpv6
add action=accept chain=forward comment="defconf: accept HIP" protocol=139
add action=accept chain=forward comment="defconf: accept IKE" dst-port=\
    500,4500 protocol=udp
add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\
    ipsec-ah
add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\
    ipsec-esp
add action=accept chain=forward comment=\
    "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
add action=drop chain=forward comment=\
    "defconf: drop everything else not coming from LAN" in-interface-list=\
    !LAN
/routing rule
add action=lookup disabled=no src-address=10.10.5.0/24 table=useWAN2
/system clock
set time-zone-autodetect=no time-zone-name=Asia/Singapore
/system identity
set name=radhAPAX2
/system logging
set 3 action=disk
add action=echo topics=critical
add action=disk topics=error
add action=disk topics=info
add action=disk topics=warning
add action=disk topics=critical
/system note
set show-at-login=no
/system ntp client
set enabled=yes
/system ntp client servers
add address=sg.pool.ntp.org
add address=time.nist.gov
add address=time.google.com
add address=time.windows.com
/system scheduler
add interval=10m name="ClouDNS Script" on-event=\
    "/system script run DDNS_Update_ClouDNS" policy=\
    ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \
    start-date=2023-10-29 start-time=09:47:22
/system script
/tool mac-server
set allowed-interface-list=MGMT
/tool mac-server mac-winbox
set allowed-interface-list=MGMT

I have hard time understanding what exactly is the issue? And how exactly things are connected together? Is nginx-proxy-manager in the same subnet as internal hosts?

nginx-proxy-manager is a container in the dedicated Docker VLAN!40 - 10.10.4.x

Most of the websites I want to use it for are in the same VLAN and also docker containers.
All the containers are setup with a custom network with their own 10.10.4.x address

Within my LAN, I cannot reach a website using the reverse proxy. eg. sub.mydomain.com doesn’t work. 10.10.4.10:8080
Externally, from outside, I can reach the servers using sub.mydomain.com

In total I have 7 VLANS, and a LAN setup on the bridge as my Unifi kit needs an untagged subnet.

I have a DDNS setup for *.mydomain.com which points to the WAN1 IP address.

I can try to draw it out if that will help.

You can put static records for these sub.mydomain.com to be resolved as NGINX local IP address into DNS service which is used on your local network.

Yeah, you’re right. I’ve been trying that just now. The DNS rewriting in AdGuard Home does work and I can now access the container web via subdomain name. The only irritation is that it keeps asking me to authenticate, the same as if I was coming from the internet. There might be some rules I can put into NPM to detect if the request is coming locally and to bypass the access list.

If authorization is on NGINX side then for sure it can be configured to act differently depending on client’s IP address (deny/allow rules per ip/subnet).

Hi, I have same problem. I have switched from HAProxy to NPM in a docker container inside a vm on proxmox and other services (vm, lxc container) inside proxmox. The services are working from WAN, but in LAN they are unreachable.
In my router I’ve set up these rules:

/ip firewall nat
add action=masquerade chain=srcnat comment="Hairpin NAT" dst-address=LAN subnet src-address=LAN subnet
add action=src-nat chain=srcnat comment="Server interni" dst-address-type="" src-address="IP NPM Host"  to-addresses=WAN IP
add action=dst-nat chain=dstnat dst-address=WAN IP dst-port=443 protocol=tcp to-addresses="IP NPM Host" 
add action=dst-nat chain=dstnat dst-address=WAN IP dst-port=80 protocol=tcp to-addresses="IP NPM Host"

but no luck.
I can’t figure out to solve. I think there is something wrong with docker and LAN network

The only way I could get it to work is by adding DNS rewrite rules so internally the sites would resolve to my NGINX reverse proxy.

@dalben Thanks, using DNS entries it works, I thinks it is the only reliable solution.

Might I ask how and where you set up those DNS rewrite rules? I’ve been facing the same issue with NGINX Reverse Proxy Manager and a Nextcloud Container running on my Unraid server. Everything works when accessing from WAN, but unfortunately not when connecting from LAN. I even added an Hairpin NAT rule, yet that didn’t work either. Did you set the rules up in Adguard Home?

Yep, setup the rules in AGH / Filters / DNS rewrites. Pointed the URLs that I use externally to the IP of the NGINX Reverse Proxy I have.

AGHDNSrw.png

Thanks! Just fyi: I got it to work by creating the hairpin NAT rule like this:

https://superuser.com/questions/663820/port-forwarding-from-inner-network-to-inner-network-hairpin-nat

Hope that works for you as well :smiley:

Thank you!!!
Many thanks both to OP and optio!
My setup seems to be more-less like OP’s and his NAT journey was identical.
Only now I was able to solve it with this simple tip! :wink:
It seems so obvious now, but it wasn’t to me, when I was reading my eyes out trying to reach to that outcome - everything is accessible from within LAN and from WAN with the same address, and letsencrypt taking automatically care of all my hosts certs!