Community discussions

MikroTik App
 
User avatar
shalak
newbie
Topic Author
Posts: 41
Joined: Sat Aug 24, 2019 11:47 am

NAT to one of my VLANs

Tue Aug 31, 2021 12:18 pm

Hello!

I'm trying to set up a my network in a secure way. The goal is to have a "SERVICE" VLAN that will be used to host various services. I want to to be able to reach those services from my "MAIN" VLAN, but not the other way around. Also, I want SERVICE to be able to reach the internet, as well as the internet to reach some of the services in SERVICE, e.g. nginx, game servers etc. via port forwarding (I have an external static IP).

I considered allowing established&related connections, then dropping all the traffic from SERVICE to MAIN. Thus machine1 in MAIN would be able to start TCP connection to machine2 in SERVICE and the machine2 will be allowed to reply. However AFAIK this won't work with connections-less protocols e.g. UDP and ICMP.

So I came up with an idea to masquerade the traffic from MAIN to SERVICE - I mean, from the MAIN perspective, the SERVICE should be treated as the internet in the usual setup.

Is this feasible? How do I do it?

Here's my VLAN and firewall part of configuration:


####### START HERE
/system identity set name="router"


#######################################
# VLAN Overview
#######################################

# 100 = main
# 101 = guest
# 102 = service
# 103 = not == Network of Things



#######################################
# Bridge
#######################################

# create one bridge, set VLAN mode off while we configure

# ARP settings are for VPN access. Thanks to this VPN hosts will "see" MAC addresses of LAN hosts.
# This should become inherited by all interfaces in this bridge, I hope
/interface bridge
add admin-mac=B8:69:F4:2F:E1:FE protocol-mode=none auto-mac=no  \
    name=BR1 vlan-filtering=no \
    arp=proxy-arp



#######################################
#
# -- Access & Hybrid Ports --
#
#######################################

# ingress behavior
/interface bridge port

# main vlan as access port, ether4 wiil be hybrid
add bridge=BR1 interface=ether2 pvid=100
add bridge=BR1 interface=ether4 pvid=100
add bridge=BR1 interface=ether5 pvid=100
add bridge=BR1 interface=wlan1 pvid=101
add bridge=BR1 interface=wlan1-not pvid=103

# Trunk. Leave pvid set to default of 1
add bridge=BR1 interface=ether3

# egress behavior
/interface bridge vlan

# Trunk & hybrid are tagged. L3 required, because we run DHCP, DNS servers, so BR1 is also tagged
# wlan1 and wlan1-not are untagged
# ether4, being hybrid port, must not be tagged for vlan 100
add bridge=BR1 tagged=BR1,ether3 vlan-ids=100
add bridge=BR1 tagged=BR1,ether3,ether4 untagged=wlan1 vlan-ids=101
add bridge=BR1 tagged=BR1,ether3,ether4 vlan-ids=102
add bridge=BR1 tagged=BR1,ether3,ether4 untagged=wlan1-not vlan-ids=103


#######################################
# VLAN Security
#######################################

# Access Ports: Only allow untagged ingress packets
/interface bridge port
set bridge=BR1 ingress-filtering=yes frame-types=admit-only-untagged-and-priority-tagged [find interface=ether2]
set bridge=BR1 ingress-filtering=yes frame-types=admit-only-untagged-and-priority-tagged [find interface=ether5]
set bridge=BR1 ingress-filtering=yes frame-types=admit-only-untagged-and-priority-tagged [find interface=wlan1]
set bridge=BR1 ingress-filtering=yes frame-types=admit-only-untagged-and-priority-tagged [find interface=wlan1-not]

# Trunk Ports: Only allow ingress packets WITH tags
set bridge=BR1 ingress-filtering=yes frame-types=admit-only-vlan-tagged [find interface=ether3]

# Hybrid: Allow ingress packets with or without tags (ingress-filtering ensures only the tags we specified)
set bridge=BR1 ingress-filtering=yes frame-types=admit-all [find interface=ether4]



#######################################
# WAN
#######################################
/interface pppoe-client
add add-default-route=yes disabled=no interface=ether1 name=pppoe-out1 use-peer-dns=yes \
### ## # --- SECRET --- # ## ###
    user={{ PPPOE_USER }} password={{ PPPOE_PASS }}

/ip dhcp-client
add interface=ether1


#######################################
# IP Services
#######################################

/interface vlan add interface=BR1 name=vlan-main-100 vlan-id=100
/interface vlan add interface=BR1 name=vlan-guest-101 vlan-id=101
/interface vlan add interface=BR1 name=vlan-service-102 vlan-id=102
/interface vlan add interface=BR1 name=vlan-not-103 vlan-id=103

/ip address add address=10.0.0.1/24 interface=vlan-main-100
/ip address add address=192.168.1.1/24 interface=vlan-guest-101
/ip address add address=10.2.0.1/24 interface=vlan-service-102
/ip address add address=10.3.0.1/24 interface=vlan-not-103



/ip pool
add name=pool-main-dhcp     ranges=10.0.0.50-10.0.0.200
add name=pool-vpn           ranges=10.0.1.100-10.0.1.120
add name=pool-vpn-local     ranges=10.0.1.200-10.0.1.220
add name=pool-guest-dhcp    ranges=192.168.1.2-192.168.1.254
add name=pool-service-dhcp  ranges=10.2.0.50-10.2.0.200
add name=pool-not-dhcp      ranges=10.3.0.50-10.3.0.200


#####################
# DHCP SERVER
#####################

/ip dhcp-server
add always-broadcast=yes disabled=no address-pool=pool-main-dhcp    interface=vlan-main-100    name=dhcp-main
add always-broadcast=yes disabled=no address-pool=pool-guest-dhcp   interface=vlan-guest-101   name=dhcp-guest
add always-broadcast=yes disabled=no address-pool=pool-not-dhcp     interface=vlan-not-103     name=dhcp-not
add always-broadcast=yes disabled=no address-pool=pool-service-dhcp interface=vlan-service-102 name=dhcp-service

# ORDER HERE IS IMPORTANT
/ip dhcp-server network
add address=10.0.0.0/24 gateway=10.0.0.1 netmask=24 dns-server=10.0.0.1 comment="main"
add address=10.2.0.0/24 gateway=10.2.0.1 netmask=24 dns-server=10.0.0.1 comment="service"
add address=10.3.0.0/24 gateway=10.3.0.1 netmask=24 dns-server=10.0.0.1 comment="not (NetworkOfThings)"
add address=192.168.1.0/24 gateway=192.168.1.1 netmask=24 comment="guest network"

## domain-search
/ip dhcp-server option add name=domain-search-option code=119 value="{{ DOMAIN_SEARCH_RFC }}"
/ip dhcp-server network set 0 dhcp-option=domain-search-option


##################################
# INTERFACE LISTS
##################################

/interface list
add name=WAN
add name=VLAN
add name=GUEST
add name=NOT
add name=LAN
add name=MAIN
add name=SERVICE
add name=VPN


/interface list member
add list=WAN     interface=ether1
add list=WAN     interface=pppoe-out1

add list=VLAN    interface=vlan-main-100
add list=VLAN    interface=vlan-guest-101
add list=VLAN    interface=vlan-service-102
add list=VLAN    interface=vlan-not-103

add list=MAIN    interface=vlan-main-100

add list=SERVICE interface=vlan-service-102

add list=NOT     interface=vlan-not-103

add list=GUEST   interface=vlan-guest-101

add list=LAN     interface=ether2
add list=LAN     interface=ether3
add list=LAN     interface=ether4
add list=LAN     interface=ether5

#############
# VPN
#############

/ppp profile
add dns-server=10.0.0.1 local-address=pool-vpn-local name=OpenVPN remote-address=pool-vpn use-encryption=required

/interface ovpn-server server
set auth=sha1 certificate=certyfikat_serwera cipher=aes256 default-profile=OpenVPN enabled=yes require-client-certificate=yes \
# MAC needed to avoid this issue: https://forum.mikrotik.com/viewtopic.php?t=17788
    mac-address=FE:49:E2:57:06:EC

/ppp secret
### ## # --- SECRET --- # ## ###
add name=user1 password="{{ user1_PASS }}" profile=OpenVPN service=ovpn
### ## # --- SECRET --- # ## ###
add name=user2 password="{{ user2_PASS }}" profile=OpenVPN service=ovpn

/interface ovpn-server add name=ovpn-user1 user=user1
/interface ovpn-server add name=ovpn-user2 user=user2

/interface list member
add list=VPN interface=ovpn-user1
add list=VPN interface=ovpn-user2

## What is this? Why do I need it?
/user group set full policy="local,telnet,ssh,ftp,reboot,read,write,policy,test,winbox,password,web,sniff,sensitive,api,romon,dude,tikapp"



###########################
# FIREWALL
###########################

/ip firewall filter

## --- INPUT

add action=accept chain=input connection-state=established,related comment="Allow Estab & Related"
add action=accept chain=input connection-state=established,related,untracked disabled=yes \
    comment="CAN_BE_DISABLED\?: defconf: accept established,related,untracked (do we need untracked if not, keep this disabled)"

add action=accept chain=input in-interface-list=GUEST dst-port=53 protocol=udp comment="Allow GUEST to DNS"
add action=reject chain=input in-interface-list=GUEST comment="Reject GUEST"

add action=accept chain=input in-interface-list=NOT dst-port=53 protocol=udp comment="Allow NOT to DNS"
add action=reject chain=input in-interface-list=NOT comment="Reject NOT"

add action=accept chain=input in-interface-list=SERVICE dst-port=53 protocol=udp comment="Allow SERVICE to DNS"
add action=reject chain=input in-interface-list=SERVICE comment="Reject SERVICE"


add action=accept chain=input in-interface-list=VLAN comment="Allow all other VLAN"

#add action=accept chain=input comment="MUST_BE_DISABLED: Allow input (for testing ONLY, ffs)" disabled=yes

add action=accept chain=input comment="Accept ICMP" protocol=icmp

add action=accept chain=input comment="Enable OpenVPN" dst-port=1194 log=yes log-prefix=OPENVPN protocol=tcp
add action=accept chain=input comment="Allow VPN users to reach router" in-interface-list=VPN log=no log-prefix=VPN_ALLOW

add action=drop   chain=input comment="SHOULD_BE_DISABLED: Drop all the rest with log" log=yes log-prefix=BLOCKED_INPUT disabled=yes
add action=drop   chain=input comment="Drop all the rest"

## --- FORWARD

add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \
    connection-state=established,related
add action=accept chain=forward connection-state=established,related comment="Allow Estab & Related"
add action=drop   chain=forward connection-state=invalid comment="defconf: drop invalid"

add action=accept chain=forward connection-state=established,related,untracked disabled=yes \
    comment="CAN_BE_DISABLED\?: defconf: accept established,related,untracked (do we need untracked if not, keep this disabled)"

add action=drop   chain=forward connection-nat-state=!dstnat \
    connection-state=new in-interface-list=WAN \
    comment="defconf:  drop all from WAN not DSTNATed"

add action=reject chain=forward in-interface-list=GUEST out-interface-list=VLAN comment="Keep GUEST away from the rest"
add action=accept chain=forward in-interface-list=GUEST out-interface-list=WAN comment="Allow GUEST to the internet"

add action=reject chain=forward in-interface-list=NOT out-interface-list=WAN comment="Keep NOT away from internet"

add action=reject chain=forward in-interface-list=SERVICE out-interface-list=WAN comment="Keep SERVICE away from internet" disabled=yes
add action=accept chain=forward in-interface-list=SERVICE out-interface-list=WAN comment="Allow SERVICE to the internet"


add action=accept chain=forward in-interface-list=MAIN out-interface-list=VLAN comment="Allow MAIN to all VLANs"
add action=accept chain=forward in-interface-list=MAIN out-interface-list=WAN comment="Allow MAIN to the internet"
add action=accept chain=forward in-interface-list=VPN out-interface-list=WAN comment="Allow VPN users to the internet"
add action=accept chain=forward in-interface-list=VPN out-interface-list=VLAN comment="Allow VPN users to all VLANs"
add action=accept chain=forward in-interface-list=dynamic out-interface-list=WAN \
    comment="Allow dynamic interfaces to internet (helps when VPN user disconnects non-gracefully)"
add action=accept chain=forward in-interface-list=dynamic out-interface-list=VLAN \
    comment="Allow dynamic interfaces to all VLANs (helps when VPN user disconnects non-gracefully)"

# services
add action=accept chain=forward in-interface-list=WAN dst-address={{ NGINX_IP }} dst-port=80 protocol=tcp \
    comment="allow 80 for nginx"
add action=accept chain=forward in-interface-list=WAN dst-address={{ NGINX_IP }} dst-port=443 protocol=tcp \
    comment="allow 443 for nginx"

add action=drop   chain=forward comment="SHOULD_BE_DISABLED: Drop all the rest with log" log=yes log-prefix=BLOCKED_FORWARD disabled=yes
add action=drop   chain=forward comment="Drop all the rest"

/ip firewall nat
add action=masquerade chain=srcnat comment="defconf: masquerade" \
    ipsec-policy=out,none out-interface-list=WAN
add action=dst-nat chain=dstnat comment="pass 80 to nginx" dst-port=80 \
    in-interface-list=WAN log=yes protocol=tcp to-addresses={{ NGINX_IP }} \
    to-ports=80 log-prefix=NGINX
add action=dst-nat chain=dstnat comment="pass 443 to nginx" dst-port=443 \
    in-interface-list=WAN log=yes protocol=tcp to-addresses={{ NGINX_IP }} \
    to-ports=443 log-prefix=NGINX_SSL



#######################################
# Turn on VLAN mode
#######################################
/interface bridge set BR1 vlan-filtering=yes

 
User avatar
mkx
Forum Guru
Forum Guru
Posts: 11452
Joined: Thu Mar 03, 2016 10:23 pm

Re: NAT to one of my VLANs

Tue Aug 31, 2021 12:55 pm

Not going into configuration details ... but (largely simplified) FW configuration as the following should do what you're after:
/ip firewall filter
add chain=forward action=accept connection-state=established,related,untracked
add chain=forward action=accept in-interface=vlan-main-100 out-interface=vlan-service-102
add chain=forward action=drop in-interface=vlan-service-102 out-interface=vlan-main-100

The first line takes care of packets belonging to already accepted connections. The second line accepts new connections originating from MAIN VLAN towards SERVICE VLAN (depending on how rules lower in forward chain are configured this rule might be redundant, implicit behaviour of firewall is to accept packets reaching the end of chain). The third line drops new connections originating from SERVICE VLAN towards MAIN VLAN.

The above should do the trick without additional trickery (NAT or whatever).

Regarding connection-less protocols: Mikrotik's stateful firewall (it's linux kernel actually) "fakes" connection states of protocols which are technically connection-less. E.g. it notes outgoing ICMP echo request packet and gladly accepts related ICMP echo reply packet (which would be dropped without it). Similarly UDP "connections" ... outgoing packet creates record in connection table and any packet in opposite direction with matching (or rather reverse) headers is passed as being part of "established" connection.
This makes configuring firewall a bit easier, but also makes behave it slightly non-deterministic in certain cases (e.g. if there's application which communicates in peer-to-peer manner over UDP, then it can kind of opens up a hole in firewall if both ends start to send packets at the same time ... firewall would normally block incoming packets but outgoing packets might create SRC-NAT hole which allows loosely related packets pass through).
 
User avatar
shalak
newbie
Topic Author
Posts: 41
Joined: Sat Aug 24, 2019 11:47 am

Re: NAT to one of my VLANs

Tue Aug 31, 2021 1:10 pm

This makes configuring firewall a bit easier, but also makes behave it slightly non-deterministic in certain cases (e.g. if there's application which communicates in peer-to-peer manner over UDP, then it can kind of opens up a hole in firewall if both ends start to send packets at the same time ... firewall would normally block incoming packets but outgoing packets might create SRC-NAT hole which allows loosely related packets pass through).

Thank you for your reply!

Wouldn't doing NAT between those two VLANs be more robust, reliable and work in all the cases? If I insist on going with NAT, is it simply the case of doing the following?
/ip firewall nat
add action=masquerade chain=srcnat comment="masquerage MAIN for SERVICE" \
    ipsec-policy=out,none in-interface-list=MAIN out-interface-list=SERVICE
 
User avatar
mkx
Forum Guru
Forum Guru
Posts: 11452
Joined: Thu Mar 03, 2016 10:23 pm

Re: NAT to one of my VLANs  [SOLVED]

Tue Aug 31, 2021 1:24 pm

Masquerading itself doesn't block connections from SERVICE towards MAIN. So you still need some (more or less selective) drop rule which does it.
In addition it messes with servers' visibility of real clients (i.e. if you perform NAT, server will see connection from router and log that ... if you want to see logged connections from real clients, you should not perform SRC-NAT on those connections ... n.b. masquerade is a fancy SRC-NAT).
If you want to have more robust firewall between VLANs, only explicitly allow what needs to be allowed (e.g. TCP to known dst-address and dst-port) which will pretty much get rid of anything you don't foresee.

I have inter-VLAN connectivity control done as per my previous suggestion and it works just fine.
 
sindy
Forum Guru
Forum Guru
Posts: 10206
Joined: Mon Dec 04, 2017 9:19 pm

Re: NAT to one of my VLANs

Tue Aug 31, 2021 1:56 pm

Just to add a point, whilst UDP, ICMP and others are not stateful protocols as such, connection tracking can still treat them as if they were thanks to the fact that they use port numbers (UDP) and an ID (ICMP echo and ICMP echo response). The rest is timeout - ICMP packets with a given (ID, IP address 1, IP address 2) tuple are considered as belonging to a known connection if the last packet with the same tuple was seen 10 s ago or less, and with UDP, the timeout for response is some 30 seconds and once the response has been seen, 3 minutes. For GRE and IPENCAP, similar approach is used, except that the signature tuple consists only of the two IP addresses and the timeout is 10 minutes (all timeout values are default ones and can be modified). So don't worry, the stateful firewall relying on connection-state can handle TCP, UDP, ICMP, SCTP, GRE... No need to complicate it using NAT.
 
User avatar
anav
Forum Guru
Forum Guru
Posts: 19125
Joined: Sun Feb 18, 2018 11:28 pm
Location: Nova Scotia, Canada
Contact:

Re: NAT to one of my VLANs

Tue Aug 31, 2021 4:10 pm

The firewall is an interesting beast
The default firewall rule set works great out of the box but in the forward chain,
you will note that it basically allows all traffic and only drops invalid and anything coming from the WAN, and this WAN blocking is mixed up with allowing port forwarding (two rules in one).
So the setup allows all traffic TO the WAN and all traffic LAN to LAN by default. Good for starting, but once you have different requirements the ball game changes.

Most recommend moving from an allow everything to block everything by default and then making allow rules for only the traffic one wishes to permit.
So in your case since traffic is allowed you have to make block rules for everything you wish to block.
If you change the default rules into block everything then you would have to make rules for everything you wish to allow. This is a more secure approach.

The way to do this is
KEEP DEFAULT RULES IN PLACE
Except for the last default rule dealing with blocking traffic from WAN that is not dst natted.
Just change this to allow dst natted traffic (if you need port forwarding and if you dont just delete the entire rule)
Then as the last rule simply block all traffic

add chain=forward action=drop comment="drop all else"

Between the forward chain default rules and the new last rule, place all allow traffic rules you need.
ex. To internet
ex. Between subnets on vlans

Make use of subnet (source-address of subnet or interface name) if you wish to control flow of traffic for one subnet in a particular direction
Make use of interface list and list members for groups of subnets you wish to control flow of traffic in a particular direction
Make use of source address for individual TP access
Make use of source-address-lists for multiple TP addresses

Who is online

Users browsing this forum: No registered users and 37 guests