AddressToString().'/'.$Node['Address']->Prefix); $Address = $Item['Address']->AddressToString(); if ($Item['Address']->Prefix != 32) $Address .= '/'.$Item['Address']->Prefix; $PacketMark = GetMarkByComment($Item['Name'].'-out'); $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'); $PacketMark = GetMarkByComment($Item['Name'].'-in'); $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'); } else { // Subnets $ParentSubnetId = GetSubgroupByRange($Node['Address']->AddressToString().'/'.$Node['Address']->Prefix); $SubnetId = GetSubgroupByRange($Item['Address']->AddressToString().'/'.$Item['Address']->Prefix); $PacketMark = GetMarkByComment($Item['Name'].'-out'); $Address = $Item['Address']->AddressToString(); if ($Item['Address']->Prefix != 32) $Address .= '/'.$Item['Address']->Prefix; $ItemsFirewall[] = array('chain' => 'inet-'.$ParentSubnetId.'-out', 'src-address' => $Address, 'out-interface' => $InetInterface, 'action' => 'jump', 'jump-target' => 'inet-'.$SubnetId.'-out', 'comment' => $Item['Name'].'-out'); $ItemsFirewall[] = array('chain' => 'inet-'.$ParentSubnetId.'-in', 'dst-address' => $Address, 'in-interface' => $InetInterface, 'action' => 'jump', 'jump-target' => 'inet-'.$SubnetId.'-in', 'comment' => $Item['Name'].'-in'); $this->ProcessNode($Item); } } if ($Node['ForceMark'] == true) { // Mark member subnets $ParentSubnetId = GetSubgroupByRange($Node['Address']->AddressToString().'/'.$Node['Address']->Prefix); $PacketMark = GetMarkByComment($Node['Name'].'-out'); $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'); $PacketMark = GetMarkByComment($Node['Name'].'-in'); $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'); } } function Run(): void { $this->RunIPv4(); $this->RunIPv6(); } function RunIPv4(): void { global $ItemsFirewall; $PathFirewall = array('ip', 'firewall', 'mangle'); $Routerboard = new Routerboard(); $Routerboard->UserName = $this->System->Config['MainRouter']['UserName']; $Routerboard->Timeout = $this->System->Config['MainRouter']['ConnectTimeout']; $Routerboard->HostName = $this->System->Config['MainRouter']['HostName']; $Routerboard->Debug = true; $InetInterface = $this->System->Config['MainRouter']['InetInterface']; // Generate address tree $AddressTree = array('Address' => new NetworkAddressIPv4(), 'Name' => 'main', 'Items' => array(), 'ForceMark' => false); // Divide rules by subnet number $DbResult = $this->System->Database->query('SELECT `Id`, `Name`, `AddressRange`, `Mask` FROM `NetworkSubnet` WHERE `Member` IS NULL'); while ($Subnet = $DbResult->fetch_assoc()) { $NewAddress = new NetworkAddressIPv4(); $NewAddress->AddressFromString($Subnet['AddressRange']); $NewAddress->Prefix = $Subnet['Mask']; InsertToAddressTreeIPv4($AddressTree, $NewAddress, 'subnet-'.RouterOSIdent($Subnet['Name'])); } // Process users $DbResult = $this->System->Database->query('SELECT `Member`.*, `Subject`.`Name` FROM `Member` '. 'LEFT JOIN `Subject` ON `Subject`.`Id` = `Member`.`Subject` '. 'WHERE `Member`.`Blocked` = 0'); while ($Member = $DbResult->fetch_assoc()) { $Member['Name'] = RouterOSIdent($Member['Name'].'-'.$Member['Id'] ); echo('Uživatel '.$Member['Name'].': '); $DbResult2 = $this->System->Database->select('NetworkDevice', '*', '`Used` = 1 AND `Member` = '.$Member['Id']); while ($Device = $DbResult2->fetch_assoc()) { $DbResult3 = $this->Database->select('NetworkInterface', '*', '`Device` = '.$Device['Id'].' AND `LocalIP` != ""'); while ($Interface = $DbResult3->fetch_assoc()) { $Name = $Device['Name']; if ($Interface['Name'] != '') $Name .= '-'.$Interface['Name']; $Name = RouterOSIdent($Name); echo($Name.', '); $NewAddress = new NetworkAddressIPv4(); $NewAddress->AddressFromString($Interface['LocalIP']); $NewAddress->Prefix = IPV4_BIT_WIDTH; InsertToAddressTreeIPv4($AddressTree, $NewAddress, $Name); } } $DbResult2 = $this->Database->select('NetworkSubnet', '*', '(`Member`='.$Member['Id'].') AND (AddressRange != "")'); while ($Subnet = $DbResult2->fetch_assoc()) { $Subnet['Name'] = RouterOSIdent('subnet-'.$Subnet['Name']); echo($Subnet['Name'].', '); $NewAddress = new NetworkAddressIPv4(); $NewAddress->AddressFromString($Subnet['AddressRange']); $NewAddress->Prefix = $Subnet['Mask']; if ($Subnet['Member'] != 0) $ForceMark = true; else $ForceMark = false; echo($ForceMark.', '); InsertToAddressTreeIPv4($AddressTree, $NewAddress, $Subnet['Name'], false, $ForceMark); } echo("\n"); } ShowSubnetNode($AddressTree); // Generate firewall rules $ItemsFirewall = array(); // Root of tree and main limit $ItemsFirewall[] = array('chain' => 'forward', 'out-interface' => $InetInterface, 'dst-address' => '!77.92.221.0/24', 'action' => 'jump', 'jump-target' => 'inet-1-out', 'comment' => 'main-out'); $ItemsFirewall[] = array('chain' => 'forward', 'in-interface' => $InetInterface, 'src-address' => '!77.92.221.0/24', 'action' => 'jump', 'jump-target' => 'inet-1-in', 'comment' => 'main-in'); $this->ProcessNode($AddressTree); // Limit direct input/output traffic to gateway $PacketMark = GetMarkByComment('rt-gateway-3-out'); $ItemsFirewall[] = array('chain' => 'output', 'out-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'local-out',); $PacketMark = GetMarkByComment('rt-gateway-3-in'); $ItemsFirewall[] = array('chain' => 'input', 'in-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'local-in',); // Limited free internet $PacketMark = GetMarkByComment('free-out'); $ItemsFirewall[] = array('chain' => 'inet-1-out', 'out-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'free-out', 'passthrough' => 'yes'); $PacketMark = GetMarkByComment('free-in'); $ItemsFirewall[] = array('chain' => 'inet-1-in', 'in-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'free-in', 'passthrough' => 'no'); // Unregistred clients add to address list $ItemsFirewall[] = array('chain' => 'inet-1-out', 'out-interface' => $InetInterface, 'src-address' => '10.145.0.0/16', 'action' => 'add-src-to-address-list', 'address-list' => 'unregistred', 'address-list-timeout' => '1d', 'comment' => 'unregistred-clients'); $Routerboard->ListUpdate($PathFirewall, array('chain', 'dst-address', 'in-interface', 'action', 'new-packet-mark', 'passthrough', 'comment', 'out-interface', 'src-address', 'jump-target'), $ItemsFirewall, array(), true); } function RunIPv6(): void { global $ItemsFirewall; $PathFirewall = array('ipv6', 'firewall', 'mangle'); $Routerboard = new Routerboard(); $Routerboard->UserName = $this->System->Config['MainRouter']['UserName']; $Routerboard->Timeout = $this->System->Config['MainRouter']['ConnectTimeout']; $Routerboard->HostName = $this->System->Config['MainRouter']['HostName']; $Routerboard->Debug = true; $InetInterface = $this->System->Config['MainRouter']['InetInterface']; // Generate address tree $AddressTree = array('Address' => new NetworkAddressIPv4(), 'Name' => 'main', 'Items' => array(), 'ForceMark' => false); // Divide rules by subnet number $DbResult = $this->System->Database->query('SELECT `Id`, `Name`, `AddressRangeIPv6`, `MaskIPv6` FROM `NetworkSubnet` '. 'WHERE (`Member` IS NULL) AND (`AddressRangeIPv6` != "")'); while ($Subnet = $DbResult->fetch_assoc()) { $NewAddress = new NetworkAddressIPv6(); $NewAddress->AddressFromString($Subnet['AddressRangeIPv6']); $NewAddress->Prefix = $Subnet['MaskIPv6']; InsertToAddressTreeIPv6($AddressTree, $NewAddress, 'subnet-'.RouterOSIdent($Subnet['Name'])); } // Process users $DbResult = $this->System->Database->query('SELECT `Member`.*, `Subject`.`Name` FROM `Member` '. 'LEFT JOIN `Subject` ON `Subject`.`Id` = `Member`.`Subject` '. 'WHERE `Member`.`Blocked` = 0'); while ($Member = $DbResult->fetch_assoc()) { $Member['Name'] = RouterOSIdent($Member['Name'].'-'.$Member['Id'] ); echo('Uživatel '.$Member['Name'].': '); $DbResult2 = $this->System->Database->select('NetworkDevice', '*', '`Used` = 1 AND `Member` = '.$Member['Id']); while ($Device = $DbResult2->fetch_assoc()) { $DbResult3 = $this->Database->select('NetworkInterface', '*', '`Device` = '.$Device['Id'].' AND `IPv6` != ""'); while ($Interface = $DbResult3->fetch_assoc()) { $Name = $Device['Name']; if ($Interface['Name'] != '') $Name .= '-'.$Interface['Name']; $Name = RouterOSIdent($Name); echo($Name.', '); $NewAddress = new NetworkAddressIPv6(); $NewAddress->AddressFromString($Interface['IPv6']); $NewAddress->Prefix = IPV6_BIT_WIDTH; InsertToAddressTreeIPv6($AddressTree, $NewAddress, $Name); } } $DbResult2 = $this->Database->select('NetworkSubnet', '*', '(`Member`='.$Member['Id'].') AND (AddressRangeIPv6 != "")'); while ($Subnet = $DbResult2->fetch_assoc()) { $Subnet['Name'] = RouterOSIdent('subnet-'.$Subnet['Name']); echo($Subnet['Name'].', '); $NewAddress = new NetworkAddressIPv6(); $NewAddress->AddressFromString($Subnet['AddressRangeIPv6']); $NewAddress->Prefix = $Subnet['MaskIPv6']; if ($Subnet['Member'] != 0) $ForceMark = true; else $ForceMark = false; echo($ForceMark.', '); InsertToAddressTreeIPv6($AddressTree, $NewAddress, $Subnet['Name'], false, $ForceMark); } echo("\n"); } ShowSubnetNode($AddressTree); // Generate firewall rules $ItemsFirewall = array(); // Root of tree and main limit $ItemsFirewall[] = array('chain' => 'forward', 'out-interface' => $InetInterface, 'dst-address' => '!2a00:e580:244::/48', 'action' => 'jump', 'jump-target' => 'inet-1-out', 'comment' => 'main-out'); $ItemsFirewall[] = array('chain' => 'forward', 'in-interface' => $InetInterface, 'src-address' => '!2a00:e580:244::/48', 'action' => 'jump', 'jump-target' => 'inet-1-in', 'comment' => 'main-in'); $this->ProcessNode($AddressTree); // Limit direct input/output traffic to gateway $PacketMark = GetMarkByComment('rt-gateway-3-out'); $ItemsFirewall[] = array('chain' => 'output', 'out-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'local-out',); $PacketMark = GetMarkByComment('rt-gateway-3-in'); $ItemsFirewall[] = array('chain' => 'input', 'in-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'local-in',); // Limited free internet $PacketMark = GetMarkByComment('free-out'); $ItemsFirewall[] = array('chain' => 'inet-1-out', 'out-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'free-out', 'passthrough' => 'yes'); $PacketMark = GetMarkByComment('free-in'); $ItemsFirewall[] = array('chain' => 'inet-1-in', 'in-interface' => $InetInterface, 'action' => 'mark-packet', 'new-packet-mark' => $PacketMark, 'comment' => 'free-in', 'passthrough' => 'no'); // Unregistred clients add to address list $ItemsFirewall[] = array('chain' => 'inet-1-out', 'out-interface' => $InetInterface, 'src-address' => '2a00:e580:244::/48', 'action' => 'add-src-to-address-list', 'address-list' => 'unregistred', 'address-list-timeout' => '1d', 'comment' => 'unregistred-clients'); $Routerboard->ListUpdate($PathFirewall, array('chain', 'dst-address', 'in-interface', 'action', 'new-packet-mark', 'passthrough', 'comment', 'out-interface', 'src-address', 'jump-target'), $ItemsFirewall, array(), true); } }