source: trunk/Modules/NetworkConfigRouterOS/Generators/FirewallMangle.php

Last change on this file was 929, checked in by chronos, 3 years ago
  • Modified: Removed commended out print_r and echo commands used only for debugging.
File size: 13.2 KB
Line 
1<?php
2
3class ConfigRouterOSFirewallMangle extends NetworkConfigItem
4{
5 function ProcessNode($Node): void
6 {
7 global $InetInterface, $ItemsFirewall;
8
9 foreach ($Node['Items'] as $Item)
10 {
11 if (count($Item['Items']) == 0)
12 {
13 // Hosts
14 $ParentSubnetId = GetSubgroupByRange($Node['Address']->AddressToString().'/'.$Node['Address']->Prefix);
15 $Address = $Item['Address']->AddressToString();
16 if ($Item['Address']->Prefix != 32) $Address .= '/'.$Item['Address']->Prefix;
17
18 $PacketMark = GetMarkByComment($Item['Name'].'-out');
19 $ItemsFirewall[] = array('chain' => 'inet-'.$ParentSubnetId.'-out', 'src-address' => $Address, 'out-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'passthrough' => 'no', 'comment' => $Item['Name'].'-out');
20 $PacketMark = GetMarkByComment($Item['Name'].'-in');
21 $ItemsFirewall[] = array('chain' => 'inet-'.$ParentSubnetId.'-in', 'dst-address' => $Address, 'in-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'passthrough' => 'no', 'comment' => $Item['Name'].'-in');
22 } else
23 {
24 // Subnets
25 $ParentSubnetId = GetSubgroupByRange($Node['Address']->AddressToString().'/'.$Node['Address']->Prefix);
26 $SubnetId = GetSubgroupByRange($Item['Address']->AddressToString().'/'.$Item['Address']->Prefix);
27 $PacketMark = GetMarkByComment($Item['Name'].'-out');
28
29 $Address = $Item['Address']->AddressToString();
30 if ($Item['Address']->Prefix != 32) $Address .= '/'.$Item['Address']->Prefix;
31
32 $ItemsFirewall[] = array('chain' => 'inet-'.$ParentSubnetId.'-out', 'src-address' => $Address, 'out-interface' => $InetInterface, 'action' => 'jump', 'jump-target' => 'inet-'.$SubnetId.'-out', 'comment' => $Item['Name'].'-out');
33 $ItemsFirewall[] = array('chain' => 'inet-'.$ParentSubnetId.'-in', 'dst-address' => $Address, 'in-interface' => $InetInterface, 'action' => 'jump', 'jump-target' => 'inet-'.$SubnetId.'-in', 'comment' => $Item['Name'].'-in');
34
35 $this->ProcessNode($Item);
36 }
37 }
38 if ($Node['ForceMark'] == true)
39 {
40 // Mark member subnets
41 $ParentSubnetId = GetSubgroupByRange($Node['Address']->AddressToString().'/'.$Node['Address']->Prefix);
42 $PacketMark = GetMarkByComment($Node['Name'].'-out');
43 $ItemsFirewall[] = array('chain' => 'inet-'.$ParentSubnetId.'-out', 'src-address' => '', 'out-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'passthrough' => 'no', 'comment' => $Node['Name'].'-all-out');
44 $PacketMark = GetMarkByComment($Node['Name'].'-in');
45 $ItemsFirewall[] = array('chain' => 'inet-'.$ParentSubnetId.'-in', 'dst-address' => '', 'in-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'passthrough' => 'no', 'comment' => $Node['Name'].'-all-in');
46 }
47 }
48
49 function Run(): void
50 {
51 $this->RunIPv4();
52 $this->RunIPv6();
53 }
54
55 function RunIPv4(): void
56 {
57 global $ItemsFirewall;
58
59 $PathFirewall = array('ip', 'firewall', 'mangle');
60
61 $Routerboard = new Routerboard();
62 $Routerboard->UserName = $this->System->Config['MainRouter']['UserName'];
63 $Routerboard->Timeout = $this->System->Config['MainRouter']['ConnectTimeout'];
64 $Routerboard->HostName = $this->System->Config['MainRouter']['HostName'];
65 $Routerboard->Debug = true;
66
67 $InetInterface = $this->System->Config['MainRouter']['InetInterface'];
68
69 // Generate address tree
70 $AddressTree = array('Address' => new NetworkAddressIPv4(), 'Name' => 'main', 'Items' => array(), 'ForceMark' => false);
71
72 // Divide rules by subnet number
73 $DbResult = $this->System->Database->query('SELECT `Id`, `Name`, `AddressRange`, `Mask` FROM `NetworkSubnet` WHERE `Member` IS NULL');
74 while ($Subnet = $DbResult->fetch_assoc())
75 {
76 $NewAddress = new NetworkAddressIPv4();
77 $NewAddress->AddressFromString($Subnet['AddressRange']);
78 $NewAddress->Prefix = $Subnet['Mask'];
79 InsertToAddressTreeIPv4($AddressTree, $NewAddress, 'subnet-'.RouterOSIdent($Subnet['Name']));
80 }
81
82 // Process users
83 $DbResult = $this->System->Database->query('SELECT `Member`.*, `Subject`.`Name` FROM `Member` '.
84 'LEFT JOIN `Subject` ON `Subject`.`Id` = `Member`.`Subject` '.
85 'WHERE `Member`.`Blocked` = 0');
86 while ($Member = $DbResult->fetch_assoc())
87 {
88 $Member['Name'] = RouterOSIdent($Member['Name'].'-'.$Member['Id'] );
89 echo('Uživatel '.$Member['Name'].': ');
90
91 $DbResult2 = $this->System->Database->select('NetworkDevice', '*', '`Used` = 1 AND `Member` = '.$Member['Id']);
92 while ($Device = $DbResult2->fetch_assoc())
93 {
94 $DbResult3 = $this->Database->select('NetworkInterface', '*', '`Device` = '.$Device['Id'].' AND `LocalIP` != ""');
95 while ($Interface = $DbResult3->fetch_assoc())
96 {
97 $Name = $Device['Name'];
98 if ($Interface['Name'] != '') $Name .= '-'.$Interface['Name'];
99 $Name = RouterOSIdent($Name);
100 echo($Name.', ');
101 $NewAddress = new NetworkAddressIPv4();
102 $NewAddress->AddressFromString($Interface['LocalIP']);
103 $NewAddress->Prefix = IPV4_BIT_WIDTH;
104 InsertToAddressTreeIPv4($AddressTree, $NewAddress, $Name);
105 }
106 }
107
108 $DbResult2 = $this->Database->select('NetworkSubnet', '*', '(`Member`='.$Member['Id'].') AND (AddressRange != "")');
109 while ($Subnet = $DbResult2->fetch_assoc())
110 {
111 $Subnet['Name'] = RouterOSIdent('subnet-'.$Subnet['Name']);
112 echo($Subnet['Name'].', ');
113 $NewAddress = new NetworkAddressIPv4();
114 $NewAddress->AddressFromString($Subnet['AddressRange']);
115 $NewAddress->Prefix = $Subnet['Mask'];
116 if ($Subnet['Member'] != 0) $ForceMark = true;
117 else $ForceMark = false;
118 echo($ForceMark.', ');
119 InsertToAddressTreeIPv4($AddressTree, $NewAddress, $Subnet['Name'], false, $ForceMark);
120 }
121 echo("\n");
122 }
123
124 ShowSubnetNode($AddressTree);
125
126 // Generate firewall rules
127 $ItemsFirewall = array();
128
129 // Root of tree and main limit
130 $ItemsFirewall[] = array('chain' => 'forward', 'out-interface' => $InetInterface, 'dst-address' => '!77.92.221.0/24', 'action' => 'jump', 'jump-target' => 'inet-1-out', 'comment' => 'main-out');
131 $ItemsFirewall[] = array('chain' => 'forward', 'in-interface' => $InetInterface, 'src-address' => '!77.92.221.0/24', 'action' => 'jump', 'jump-target' => 'inet-1-in', 'comment' => 'main-in');
132
133 $this->ProcessNode($AddressTree);
134
135 // Limit direct input/output traffic to gateway
136 $PacketMark = GetMarkByComment('rt-gateway-3-out');
137 $ItemsFirewall[] = array('chain' => 'output', 'out-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'local-out',);
138 $PacketMark = GetMarkByComment('rt-gateway-3-in');
139 $ItemsFirewall[] = array('chain' => 'input', 'in-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'local-in',);
140
141 // Limited free internet
142 $PacketMark = GetMarkByComment('free-out');
143 $ItemsFirewall[] = array('chain' => 'inet-1-out', 'out-interface' => $InetInterface,
144 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'free-out', 'passthrough' => 'yes');
145 $PacketMark = GetMarkByComment('free-in');
146 $ItemsFirewall[] = array('chain' => 'inet-1-in', 'in-interface' => $InetInterface,
147 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'free-in', 'passthrough' => 'no');
148 // Unregistred clients add to address list
149 $ItemsFirewall[] = array('chain' => 'inet-1-out', 'out-interface' => $InetInterface, 'src-address' => '10.145.0.0/16',
150 'action' => 'add-src-to-address-list', 'address-list' => 'unregistred', 'address-list-timeout' => '1d',
151 'comment' => 'unregistred-clients');
152
153 $Routerboard->ListUpdate($PathFirewall, array('chain', 'dst-address', 'in-interface', 'action', 'new-packet-mark', 'passthrough', 'comment', 'out-interface', 'src-address', 'jump-target'), $ItemsFirewall, array(), true);
154 }
155
156 function RunIPv6(): void
157 {
158 global $ItemsFirewall;
159
160 $PathFirewall = array('ipv6', 'firewall', 'mangle');
161
162 $Routerboard = new Routerboard();
163 $Routerboard->UserName = $this->System->Config['MainRouter']['UserName'];
164 $Routerboard->Timeout = $this->System->Config['MainRouter']['ConnectTimeout'];
165 $Routerboard->HostName = $this->System->Config['MainRouter']['HostName'];
166 $Routerboard->Debug = true;
167
168 $InetInterface = $this->System->Config['MainRouter']['InetInterface'];
169
170 // Generate address tree
171 $AddressTree = array('Address' => new NetworkAddressIPv4(), 'Name' => 'main', 'Items' => array(), 'ForceMark' => false);
172
173 // Divide rules by subnet number
174 $DbResult = $this->System->Database->query('SELECT `Id`, `Name`, `AddressRangeIPv6`, `MaskIPv6` FROM `NetworkSubnet` '.
175 'WHERE (`Member` IS NULL) AND (`AddressRangeIPv6` != "")');
176 while ($Subnet = $DbResult->fetch_assoc())
177 {
178 $NewAddress = new NetworkAddressIPv6();
179 $NewAddress->AddressFromString($Subnet['AddressRangeIPv6']);
180 $NewAddress->Prefix = $Subnet['MaskIPv6'];
181 InsertToAddressTreeIPv6($AddressTree, $NewAddress, 'subnet-'.RouterOSIdent($Subnet['Name']));
182 }
183
184 // Process users
185 $DbResult = $this->System->Database->query('SELECT `Member`.*, `Subject`.`Name` FROM `Member` '.
186 'LEFT JOIN `Subject` ON `Subject`.`Id` = `Member`.`Subject` '.
187 'WHERE `Member`.`Blocked` = 0');
188 while ($Member = $DbResult->fetch_assoc())
189 {
190 $Member['Name'] = RouterOSIdent($Member['Name'].'-'.$Member['Id'] );
191 echo('Uživatel '.$Member['Name'].': ');
192
193 $DbResult2 = $this->System->Database->select('NetworkDevice', '*', '`Used` = 1 AND `Member` = '.$Member['Id']);
194 while ($Device = $DbResult2->fetch_assoc())
195 {
196 $DbResult3 = $this->Database->select('NetworkInterface', '*', '`Device` = '.$Device['Id'].' AND `IPv6` != ""');
197 while ($Interface = $DbResult3->fetch_assoc())
198 {
199 $Name = $Device['Name'];
200 if ($Interface['Name'] != '') $Name .= '-'.$Interface['Name'];
201 $Name = RouterOSIdent($Name);
202 echo($Name.', ');
203 $NewAddress = new NetworkAddressIPv6();
204 $NewAddress->AddressFromString($Interface['IPv6']);
205 $NewAddress->Prefix = IPV6_BIT_WIDTH;
206 InsertToAddressTreeIPv6($AddressTree, $NewAddress, $Name);
207 }
208 }
209
210 $DbResult2 = $this->Database->select('NetworkSubnet', '*', '(`Member`='.$Member['Id'].') AND (AddressRangeIPv6 != "")');
211 while ($Subnet = $DbResult2->fetch_assoc())
212 {
213 $Subnet['Name'] = RouterOSIdent('subnet-'.$Subnet['Name']);
214 echo($Subnet['Name'].', ');
215 $NewAddress = new NetworkAddressIPv6();
216 $NewAddress->AddressFromString($Subnet['AddressRangeIPv6']);
217 $NewAddress->Prefix = $Subnet['MaskIPv6'];
218 if ($Subnet['Member'] != 0) $ForceMark = true;
219 else $ForceMark = false;
220 echo($ForceMark.', ');
221 InsertToAddressTreeIPv6($AddressTree, $NewAddress, $Subnet['Name'], false, $ForceMark);
222 }
223 echo("\n");
224 }
225
226 ShowSubnetNode($AddressTree);
227
228 // Generate firewall rules
229 $ItemsFirewall = array();
230
231 // Root of tree and main limit
232 $ItemsFirewall[] = array('chain' => 'forward', 'out-interface' => $InetInterface, 'dst-address' => '!2a00:e580:244::/48',
233 'action' => 'jump', 'jump-target' => 'inet-1-out', 'comment' => 'main-out');
234 $ItemsFirewall[] = array('chain' => 'forward', 'in-interface' => $InetInterface, 'src-address' => '!2a00:e580:244::/48',
235 'action' => 'jump', 'jump-target' => 'inet-1-in', 'comment' => 'main-in');
236
237 $this->ProcessNode($AddressTree);
238
239 // Limit direct input/output traffic to gateway
240 $PacketMark = GetMarkByComment('rt-gateway-3-out');
241 $ItemsFirewall[] = array('chain' => 'output', 'out-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'local-out',);
242 $PacketMark = GetMarkByComment('rt-gateway-3-in');
243 $ItemsFirewall[] = array('chain' => 'input', 'in-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'local-in',);
244
245 // Limited free internet
246 $PacketMark = GetMarkByComment('free-out');
247 $ItemsFirewall[] = array('chain' => 'inet-1-out', 'out-interface' => $InetInterface,
248 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'free-out', 'passthrough' => 'yes');
249 $PacketMark = GetMarkByComment('free-in');
250 $ItemsFirewall[] = array('chain' => 'inet-1-in', 'in-interface' => $InetInterface,
251 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'free-in', 'passthrough' => 'no');
252 // Unregistred clients add to address list
253 $ItemsFirewall[] = array('chain' => 'inet-1-out', 'out-interface' => $InetInterface, 'src-address' => '2a00:e580:244::/48',
254 'action' => 'add-src-to-address-list', 'address-list' => 'unregistred', 'address-list-timeout' => '1d',
255 'comment' => 'unregistred-clients');
256
257 $Routerboard->ListUpdate($PathFirewall, array('chain', 'dst-address', 'in-interface', 'action', 'new-packet-mark',
258 'passthrough', 'comment', 'out-interface', 'src-address', 'jump-target'), $ItemsFirewall, array(), true);
259 }
260}
Note: See TracBrowser for help on using the repository browser.