1
0

IpAddressClassifier.php 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * @copyright 2022 Christoph Wurst <christoph@winzerhof-wurst.at>
  5. *
  6. * @author 2022 Christoph Wurst <christoph@winzerhof-wurst.at>
  7. *
  8. * @license GNU AGPL version 3 or any later version
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License as
  12. * published by the Free Software Foundation, either version 3 of the
  13. * License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Affero General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Affero General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. namespace OC\Net;
  24. use IPLib\Address\IPv6;
  25. use IPLib\Factory;
  26. use IPLib\ParseStringFlag;
  27. use Symfony\Component\HttpFoundation\IpUtils;
  28. use function filter_var;
  29. /**
  30. * Classifier for IP addresses
  31. *
  32. * @internal
  33. */
  34. class IpAddressClassifier {
  35. private const LOCAL_ADDRESS_RANGES = [
  36. '100.64.0.0/10', // See RFC 6598
  37. '192.0.0.0/24', // See RFC 6890
  38. ];
  39. /**
  40. * Check host identifier for local IPv4 and IPv6 address ranges
  41. *
  42. * Hostnames are not considered local. Use the HostnameClassifier for those.
  43. */
  44. public function isLocalAddress(string $ip): bool {
  45. $parsedIp = Factory::parseAddressString(
  46. $ip,
  47. ParseStringFlag::IPV4_MAYBE_NON_DECIMAL | ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED
  48. );
  49. if ($parsedIp === null) {
  50. /* Not an IP */
  51. return false;
  52. }
  53. /* Replace by normalized form */
  54. if ($parsedIp instanceof IPv6) {
  55. $ip = (string)($parsedIp->toIPv4() ?? $parsedIp);
  56. } else {
  57. $ip = (string)$parsedIp;
  58. }
  59. if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
  60. /* Range address */
  61. return true;
  62. }
  63. if (IpUtils::checkIp($ip, self::LOCAL_ADDRESS_RANGES)) {
  64. /* Within local range */
  65. return true;
  66. }
  67. return false;
  68. }
  69. }