Filtre pare-feu Mikrotik: script générant la base d'une politique de filtrage

Quiconque a déjà écrit une politique de filtrage de pare-feu sait que ce n'est pas une question simple et implique beaucoup d'erreurs lorsqu'il y a plus de 2 zones réseau. Le script de cet article vous aidera dans cet essai.

introduction


Par zone réseau, j'entends un ensemble d'interfaces ou d'adresses IP pour lesquelles la règle de filtrage s'applique. Dans mon script, les adresses IP de zone sont attribuées à l'interface. Autrement dit, si nous attendons des adresses IP «de confiance» du réseau local, il sera étrange que les connexions correspondantes arrivent du fournisseur.

Comment ça marche


Tout tourne autour de la description des zones oĂą l'on se demande comment elles interagissent entre elles.
Dans ma configuration, si aucune autre règle n'est définie, tout le trafic sera abandonné avec la règle DROP, nous allons donc définir les règles ACCEPTER et REJETER.

Ensuite, le script dans une boucle passe par toutes les descriptions de zone et crée:

  • Listes d'interface IF- <nom de zone>
  • Listes d'adresses IP <nom de zone>
  • DĂ©finit la configuration par dĂ©faut et lĂ©gèrement complĂ©tĂ©e par le filtre, le mangle et la configuration brute

La zone de destination du trafic IP de l'interface diffère en ce que son nom ne figure pas dans la section des interfaces. Ainsi, le script comprend où nous avons le but de ip, et où est l'interface.

Variables


  • gping - Autorise le ping dans toutes les directions et lors du transfert. En d'autres termes, il sera possible de pinguer mĂŞme ce qui a Ă©tĂ© fermĂ© par d'autres règles dans le filtre. Inclure comme souhaitĂ©;)
  • debug - Mettez la règle ACCEPT au tout dĂ©but des chaĂ®nes racine, ce qui rend toutes les autres règles inutiles. Très utile au stade du dĂ©bogage des règles. Appliquez la stratĂ©gie comme vous le souhaitez, activez le mode sans Ă©chec, puis dĂ©sactivez ces règles. Si le routeur est devenu indisponible, après 10 secondes, les règles seront Ă  nouveau activĂ©es et vous pourrez penser, de quoi vous Ă©tiez-vous trompĂ©?
  • allout - Autorise le trafic sortant du routeur, gĂ©nĂ©ralement le routeur ne gĂ©nère pas de mauvais trafic, donc dans un certain nombre de configurations, cela est acceptable.

Description des zones


La description elle-même est divisée en deux blocs: les interfaces et les adresses IP. Il existe des variables spéciales pour les interfaces:

  • is_wan: ajoute des règles de traitement des tunnels et DNS
  • do_masq: ajoute des règles de masquage du trafic Ă  cette zone
  • is_lan: ajoute des règles pour rĂ©pondre Ă  DHCP et DNS
  • mss: mss ,
  • ADDoS: DDoS . — ( ) , IP . :
    • gen — generic, , .
    • mngr — managment, mikrotik (winbox, ssh)
    • — , .


Il existe également deux zones spéciales: rt, il s’agit du routeur lui-même, et toutes, car il n’est pas difficile de deviner «n’importe quelle direction», toutes ne peuvent pas être spécifiées comme source de trafic.

L'action principale du script est de créer une série de règles de saut avec filtrage par source et destination du trafic, qui se terminent par une règle avec ACCEPTER ou REJETER.

La description de la zone peut être réduite, comme dans l'exemple pour ISP et rt (devrait toujours l'être).

Si vous souhaitez terminer la chaîne avec votre règle, ajoutez simplement personnalisé (ou autre) dans la description de la zone au lieu d'accepter ou de rejeter, alors la chaîne de saut ne sera complétée par aucune règle, et vous pouvez la créer vous-même.

Explication des règles du script


Zones
:local gping 1
:local debug 0
:local zones {
	"if"={
		"ISP"={
			"is_wan"=1;
			"do_masq"=1;
			"ADDoS"={
				mngr={
					dst-limit="4/1m,1,src-address/1m40s";
					timeout="1d";
					comment="Blocking bruteforcing winbox & ssh port";
					excl=[:toarray ("Trusted")];
				};
				gen={
					dst-limit="50,50,src-address/10s";
					timeout="1d";
					comment="Blocking potential DDoS";
					excl=[:toarray ("Trusted")];
				};
			};
		};
		"LAN"={
			"is_lan"=1;
			policy={ 
				"all"="accept";
			};
		};
		"TUN"={
			mss=1400;
		};
		"rt"={};
	};
	"ip"={
		"rt"={
			policy={
				"all"="accept" 
			};
		};
		"TUN"={
			"Staff"={
				"Server"="accept";
			};
			"Manager"={
				"all"="accept";
			};
		};
		"ISP"={
			"Trusted"={
				"rt"="accept";
			};
		};
	};
}


Il y a 4 zones pour les interfaces, dont une est obligatoire rt:

  • Le FAI est pour le fournisseur, par consĂ©quent, il est indiquĂ© de crĂ©er des règles supplĂ©mentaires pour certains protocoles.
  • LAN - pour un rĂ©seau local, on lui donne des règles pour le lan et il y a une action gĂ©nĂ©rale permettant dans n'importe quelle direction.
  • TUN - pour les tunnels appropriĂ©s, la correction MSS est indiquĂ©e.

B 3e zones ip:

  • Personnel et Manager sur les interfaces TUN:
    • Personnel - n'a accès qu'Ă  la zone ip du serveur
    • Manager - peut aller n'importe oĂą

  • Trusted sur l'interface ISP a accès au routeur

filtre-gen
# may/13/2020 10:00:00 by RouterOS 6.46.6
# RoS filter generator v 0.9.5

:local gping 0
:local debug 1
:local allout 1
:local zones {
	"if"={
		"ISP"={
			"is_wan"=1;
			"do_masq"=1;
			"ADDoS"={
				mngr={
					dst-limit="4/1m,1,src-address/1m40s";
					timeout="1d";
					comment="Blocking bruteforcing winbox & ssh port";
					excl=[:toarray ("Trusted")];
				};
				gen={
					dst-limit="50,50,src-address/10s";
					timeout="1d";
					comment="Blocking potential DDoS";
					excl=[:toarray ("Trusted")];
				};
			};
		};
		"LAN"={
			"is_lan"=1;
			policy={ 
				"all"="accept";
			};
		};
		"TUN"={
			mss=1400;
		};
		"rt"={};
	};
	"ip"={
		"rt"={
			policy={
				"all"="accept" 
			};
		};
		"TUN"={
			"Staff"={
				"Server"="accept";
			};
			"Manager"={
				"all"="accept";
			};
		};
		"ISP"={
			"Trusted"={
				"rt"="accept";
			};
		};
	};
}
/ip firewall raw
add action=notrack chain=prerouting ipsec-policy=in,ipsec comment="Notrack ipsec"
add action=notrack chain=prerouting dst-address-type=multicast comment="Notrack multicast"
/ip firewall filter
:if ( ($debug)=0 ) do={
	add action=accept chain=forward comment=DEBUG!!! disabled=yes
	add action=accept chain=input comment=DEBUG!!! disabled=yes
	add action=accept chain=output comment=DEBUG!!! disabled=yes
} else={
	add action=accept chain=forward comment=DEBUG!!!
	add action=accept chain=input comment=DEBUG!!!
	add action=accept chain=output comment=DEBUG!!!
}
add action=accept chain=input comment="defconf: accept to local loopback (for CAPsMAN)" dst-address=127.0.0.1 dst-port=5246,5247 protocol=udp src-address-type=local
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=jump chain=input comment="defconf: new input" connection-state=new jump-target=in-new
add action=jump chain=input comment="defconf: notrack input" jump-target=in-notrack
add action=drop chain=input comment="defconf: drop all not allowed"
add action=accept chain=output comment="defconf: accept established,related,untracked" connection-state=established,related,untracked
add action=jump chain=output comment="defconf: new output" connection-state=new jump-target=out-new
add action=jump chain=output comment="defconf: notrack output" jump-target=out-notrack
:if ( ($allout)=1 ) do={
	add action=accept chain=out-notrack comment="defconf: Allow any trafic from rt"
} else={
	add action=accept chain=out-notrack comment="defconf: Allow any trafic from rt" disabled=yes
}
add action=drop chain=output comment="defconf: drop all not allowed"
add action=accept chain=forward comment="defconf: accept in ipsec policy" ipsec-policy=in,ipsec
add action=accept chain=forward comment="defconf: accept out ipsec policy" ipsec-policy=out,ipsec
add action=fasttrack-connection chain=forward comment="defconf: fasttrack" connection-mark=no-mark connection-state=established,related
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=jump chain=forward comment="defconf: new forward" connection-state=new jump-target=fw-new
add action=jump chain=forward comment="defconf: notrack forward" jump-target=fw-notrack
add action=accept chain=forward comment="defconf: Accept all forward DSTNATed" connection-nat-state=dstnat
add action=drop chain=forward comment="defconf: drop all not allowed for forward"
:if ( ($gping)=1 ) do={
	add action=accept chain=WAN2RT-STD-PROTO comment=ICMP protocol=icmp disabled=yes
} else={
	add action=accept chain=WAN2RT-STD-PROTO comment=ICMP protocol=icmp
}
add action=accept chain=WAN2RT-STD-PROTO comment=GRE ipsec-policy=in,ipsec protocol=gre
add action=accept chain=WAN2RT-STD-PROTO comment=IPSec protocol=ipsec-esp
add action=accept chain=WAN2RT-STD-PROTO comment=IPSec protocol=ipsec-ah
add action=accept chain=WAN2RT-STD-PROTO comment="IPSec encapsulated" dst-port=500,4500 protocol=udp
add action=accept chain=WAN2RT-STD-PROTO comment=L2TP dst-port=1701 ipsec-policy=in,ipsec protocol=udp
add action=accept chain=WAN2RT-STD-PROTO comment=PPtP dst-port=1723 protocol=tcp
add action=accept chain=LAN2RT-STD-PROTO comment=DNS dst-port=53 protocol=tcp
add action=accept chain=LAN2RT-STD-PROTO comment=NTP,DNS,DHCP dst-port=53,123,67-68 protocol=udp
add action=accept chain=LAN2RT-STD-PROTO comment=DHCP dst-port=67-68 protocol=udp
add action=accept chain=RT2WAN-STD-PROTO comment=DNS dst-port=53 protocol=tcp
add action=accept chain=RT2WAN-STD-PROTO comment=NTP,DNS dst-port=53,123 protocol=udp
add action=accept chain=WAN2RT-STD-PROTO comment=IPSec protocol=ipsec-esp
add action=accept chain=RT2WAN-STD-PROTO comment=IPSec protocol=ipsec-ah
add action=accept chain=RT2WAN-STD-PROTO comment="IPSec encapsulated" dst-port=500,4500 protocol=udp
add action=reject chain=RT2WAN-STD-PROTO comment=GRE ipsec-policy=out,none protocol=gre reject-with=icmp-admin-prohibited
add action=reject chain=RT2WAN-STD-PROTO comment=L2TP dst-port=1701 ipsec-policy=out,none protocol=udp reject-with=icmp-admin-prohibited
:if ( ($gping)=1 ) do={
	add action=accept chain=fw-new comment=ICMP protocol=icmp
	add action=accept chain=in-new comment=ICMP protocol=icmp
	add action=accept chain=out-new comment=ICMP protocol=icmp
} else={
	add action=accept chain=fw-new comment=ICMP protocol=icmp disabled=yes
	add action=accept chain=in-new comment=ICMP protocol=icmp disabled=yes
	add action=accept chain=out-new comment=ICMP protocol=icmp disabled=yes
}
/ip firewall filter
:foreach zone,conf in=($zones->"if") do={
	:if ( ($zone)!="rt" ) do={
		:if ( [/interface list print count-only where name=("IF-".$zone)] = 0) do={
			/interface list add name=("IF-".$zone)
		}
		add action=jump chain=fw-new in-interface-list=("IF-".$zone) comment=("Fwd plc from if ".$zone) jump-target=("fw-plc-s:".$zone)
		add action=jump chain=in-new in-interface-list=("IF-".$zone) comment=("In plc for if ".$zone) jump-target=("in-plc-s:".$zone)
		:foreach ddos,val in=($conf->"ADDoS") do={
			:if ( $ddos="mngr" ) do={
				add action=jump chain=("in-plc-s:".$zone) dst-port=22,8291 jump-target=("ADDoS-s:".$zone."-".$ddos) comment=("AntiDDoS for ".$ddos." from ".$zone) protocol=tcp
			}
			:if ( $ddos="gen" ) do={
				add action=jump chain=("in-plc-s:".$zone) jump-target=("ADDoS-s:".$zone."-".$ddos) comment=("AntiDDoS for ".$ddos." from ".$zone)
			}
			:if ( $ddos="mngr" || $ddos="gen" ) do={
				:foreach excl in=(($val)->"excl") do={ 
					add action=return chain=("ADDoS-s:".$zone."-".$ddos) comment=("Execption for ".$excl." from ".$zone) src-address-list=("IP-".$excl)
				}
				add action=return chain=("ADDoS-s:".$zone."-".$ddos) comment=("Limit number incoming connections for ".$ddos." from ".$zone) dst-limit=(($val)->"dst-limit")
				add action=add-src-to-address-list address-list=("IP-DDoS-s:".$zone."-".$ddos) address-list-timeout=(($val)->"timeout") chain=("ADDoS-s:".$zone."-".$ddos) comment=("Add to IP-DDoS-".$ddos." list from ".$zone)
			}
			:if ( $ddos!="mngr" && $ddos!="gen" ) do={
				add action=jump chain=("in-plc-s:".$zone) jump-target=("ADDoS-".$ddos) comment=("AntiDDoS for ".$ddos." from ".$zone) disabled=yes
				:foreach excl in=(($val)->"excl") do={ 
					add action=return chain=("ADDoS-s:".$zone."-".$ddos) comment=("Execption for ".$excl." from ".$zone) src-address-list=("IP-".$excl)
				}
				add action=return chain=("ADDoS-s:".$zone."-".$ddos) comment=("Limit number incoming connections for ".$ddos." from ".$zone) dst-limit=(($val)->"dst-limit")
				add action=add-src-to-address-list address-list=("IP-DDoS-s:".$zone."-".$ddos) address-list-timeout=(($val)->"timeout") chain=("ADDoS-s:".$zone."-".$ddos) comment=("Add to IP-DDoS-".$ddos." list from ".$zone)
			}
			/ip firewall raw add action=drop chain=prerouting comment=("DROP Banned by ".$ddos." from ".$zone) in-interface-list=("IF-".$zone) src-address-list=("IP-DDoS-s:".$zone."-".$ddos)
		}
	} else={
		add action=jump chain=out-new comment=("Out plc for rt") jump-target="out-plc-s:rt"
	}	
}
:foreach zone,conf in=($zones->"if") do={
	:if ( ($zone)!="rt" && ($zone)!="all") do={
		:if ( ($conf->"is_lan")=1 || ($conf->"is_wan")=1 ) do={
			add action=jump chain=in-notrack comment=("In Allow plc for STD LAN PROTO from ".$zone) in-interface-list=("IF-".$zone) jump-target=LAN2RT-STD-PROTO
		}
		:if ( ($conf->"is_wan")=1) do={
			add action=jump chain=in-notrack comment=("In Allow plc for STD WAN PROTO from ".$zone) in-interface-list=("IF-".$zone) jump-target=WAN2RT-STD-PROTO
			add action=jump chain=out-notrack out-interface-list=("IF-".$zone) comment=("Out Allow plc for STD WAN PROTO to ".$zone) jump-target=RT2WAN-STD-PROTO
		}
		:if ( ($conf->"do_masq")=1) do={
			/ip firewall nat add action=masquerade chain=srcnat out-interface-list=("IF-".$zone) comment=("Masquerade traffic going to ".$zone)
		}
		:if ( [:len ($conf->"mss")]!=0 ) do={
			/ip firewall mangle add action=change-mss chain=forward in-interface-list=("IF-".$zone) new-mss=($conf->"mss") passthrough=yes protocol=tcp tcp-flags=syn tcp-mss=(($conf->"mss"+1)."-65535") comment=("Fix mss on tunel ".$zone)
			/ip firewall mangle add action=change-mss chain=forward out-interface-list=("IF-".$zone) new-mss=($conf->"mss") passthrough=yes protocol=tcp tcp-flags=syn tcp-mss=(($conf->"mss"+1)."-65535") comment=("Fix mss on tunel ".$zone)
		}
		:foreach src,val in=(($zones->"ip")->$"zone") do={
			:foreach tgt,policy in=$val do={
				:if ( ($tgt)!="rt" && ($tgt)!="all") do={
					:if ( [:len (($zones->"if")->$"tgt")]=0 ) do={
						add action=jump chain=("fw-plc-s:".$zone) src-address-list=("IP-".$src) dst-address-list=("IP-".$tgt) comment=("Fwd plc from if ".$zone." & ip ".$src." to ".$tgt) jump-target=("fw-plc-s:".$zone."&".$src.">".$tgt)
					} else={
						add action=jump chain=("fw-plc-s:".$zone) src-address-list=("IP-".$src) out-interface-list=("IF-".$tgt) comment=("Fwd plc from if ".$zone." & ip ".$src." to ".$tgt) jump-target=("fw-plc-s:".$zone."&".$src.">".$tgt)
					}
					:if ( ($policy)="accept") do={
						add action=accept chain=("fw-plc-s:".$zone."&".$src.">".$tgt) comment=("Fwd plc from if ".$zone." & ip ".$src." Accept to ".$tgt)
					}
					:if ( ($policy)="reject") do={
						add action=reject chain=("fw-plc-s:".$zone."&".$src.">".$tgt) comment=("Fwd plc from if ".$zone." & ip ".$src." Reject to ".$tgt)
					}
				}
				:if ( ($tgt)="rt" ) do={
					add action=jump chain=("in-plc-s:".$zone) src-address-list=("IP-".$src) comment=("In plc for if ".$zone." & ip ".$src." to rt") jump-target=("in-plc-s:".$zone."&".$src.">rt")
					:if ( ($policy)="accept") do={
						add action=accept chain=("in-plc-s:".$zone."&".$src.">rt") comment=("In plc for if ".$zone." & ip ".$src." Accept to rt")
					}
					:if ( ($policy)="reject") do={
						add action=reject chain=("in-plc-s:".$zone."&".$src.">rt") comment=("In plc for if ".$zone." & ip ".$src." Accept to rt")
					}
				}
				:if ( ($tgt)="all" ) do={
					add action=jump chain=("fw-plc-s:".$zone) src-address-list=("IP-".$src) comment=("Fwd plc from if ".$zone." & ip ".$src." to All") jump-target=("fw-plc-s:".$zone."&".$src.">all")
					add action=jump chain=("in-plc-s:".$zone) src-address-list=("IP-".$src) comment=("In plc for if ".$zone." & ip ".$src." to All") jump-target=("in-plc-s:".$zone."&".$src.">all")
					:if ( ($policy)="accept") do={
						add action=accept chain=("fw-plc-s:".$zone."&".$src.">all") comment=("Fwd plc from if ".$zone." & ip ".$src." Accept to All")
						add action=accept chain=("in-plc-s:".$zone."&".$src.">all") comment=("In plc from if ".$zone." & ip ".$src." Accept to All")
					}
					:if ( ($policy)="reject") do={
						add action=reject chain=("fw-plc-s:".$zone."&".$src.">all") comment=("Fwd plc from if ".$zone." & ip ".$src." Reject to All")
						add action=reject chain=("in-plc-s:".$zone."&".$src.">all") comment=("In plc from if ".$zone." & ip ".$src." Reject to All")
					}
				}
			}
		}
		:foreach tgt,policy in=($conf->"policy") do={
			:if ( ($tgt)!="rt" && ($tgt)!="all") do={
				:if ( [:len (($zones->"if")->$"tgt")]=0 ) do={
					add action=jump chain=("fw-plc-s:".$zone) dst-address-list=("IP-".$tgt) comment=("Fwd plc from if ".$zone." to ".$tgt) jump-target=("fw-plc-s:".$zone.">".$tgt)
				} else={
					add action=jump chain=("fw-plc-s:".$zone) out-interface-list=("IF-".$tgt) comment=("Fwd plc from if ".$zone." to ".$tgt) jump-target=("fw-plc-s:".$zone.">".$tgt)
				}
				:if ( ($policy)="accept") do={
					add action=accept chain=("fw-plc-s:".$zone.">".$tgt) comment=("Fwd plc from if ".$zone." Accept to ".$tgt)
				}
				:if ( ($policy)="reject") do={
					add action=reject chain=("fw-plc-s:".$zone.">".$tgt) comment=("Fwd plc from if ".$zone." Reject to ".$tgt)
				}
			}
			:if ( ($tgt)="rt" ) do={
				:if ( ($conf->"is_lan")!=1 && ($conf->"is_wan")!=1 ) do={
					add action=jump chain=("in-plc-s:".$zone) comment=("In plc for if ".$zone." to rt") jump-target=("in-plc-s:".$zone.">rt")
				}
				:if ( ($policy)="accept") do={
					add action=accept chain=("in-plc-s:".$zone.">rt") comment=("In plc for if ".$zone." Accept to rt")
				}
				:if ( ($policy)="reject") do={
					add action=reject chain=("in-plc-s:".$zone.">rt") comment=("In plc for if ".$zone." Reject to rt")
				}
			}
			:if ( ($tgt)="all" ) do={
				add action=jump chain=("fw-plc-s:".$zone) comment=("Fwd plc from if ".$zone." to All") jump-target=("fw-plc-s:".$zone.">all")
				add action=jump chain=("in-plc-s:".$zone) comment=("In plc for if ".$zone." to All") jump-target=("in-plc-s:".$zone.">all")
				:if ( ($policy)="accept") do={
					add action=accept chain=("fw-plc-s:".$zone.">all") comment=("Fwd plc from if ".$zone." Accept to All")
					add action=accept chain=("in-plc-s:".$zone.">all") comment=("In plc from if ".$zone." Accept to All")
				}
				:if ( ($policy)="reject") do={
					add action=reject chain=("fw-plc-s:".$zone.">all") comment=("Fwd plc from if ".$zone." Reject to All")
					add action=reject chain=("in-plc-s:".$zone.">all") comment=("In plc from if ".$zone." Reject to All")
				}
			}
		}
	}
}


Conclusion


Ce script m'a aidé à simplifier considérablement la configuration de politiques complexes, mais il peut encore contenir des erreurs. Avant utilisation, consultez un spécialiste. En cas de détection d'effets secondaires, écrivez, nous corrigerons.

All Articles