Ferramentas / Validador de IP e CIDR

Validador de IP e CIDR

Digite um IP (v4 ou v6) ou um bloco CIDR como 192.168.1.10/24 e veja a rede, a faixa, a máscara e a quantidade de hosts.

Processamento local: nada do que você digita sai do seu navegador.

Como usar

Digite um endereço (192.168.0.1, 2001:db8::1) ou um bloco CIDR (10.0.0.0/8, 2001:db8::/32). Para IPv4 mostramos rede, primeiro e último endereço, máscara, wildcard, total de endereços e hosts utilizáveis. Para IPv6, a faixa e o total de endereços. No segundo campo você pode testar se um IP pertence ao bloco.

Como contamos os hosts

  • Em IPv4 comum, hosts utilizáveis = total de endereços menos 2 (o da rede e o de broadcast).
  • /31 tem 2 endereços utilizáveis (RFC 3021, enlaces ponto a ponto) e /32 identifica um único host.
  • Em IPv6 não há broadcast, então todos os endereços do bloco contam.

Regras de formato

No IPv4, cada um dos 4 octetos vai de 0 a 255 e não aceita zero à esquerda (01), que alguns sistemas leem como octal. No IPv6, grupos de até 4 dígitos hexadecimais e no máximo um ::. Também reconhecemos faixas especiais (privado, loopback, link-local etc.).

Como implementar em código

Exemplos prontos para usar no seu projeto.

const ipv4 = s => { const p = s.split('.'); return p.length === 4 && p.every(o => /^(0|[1-9]\d{0,2})$/.test(o) && +o <= 255); };
// O parser de URL valida IPv6 dentro de colchetes
const ipv6 = s => { try { new URL(`http://[${s}]/`); return s.includes(':'); } catch { return false; } };

const str = n => [24, 16, 8, 0].map(s => (n >>> s) & 255).join('.');

function cidrV4(cidr) {
  const [ip, pf] = cidr.split('/'), p = Number(pf);
  if (!ipv4(ip) || !/^\d+$/.test(pf) || p > 32) return null;
  const n = ip.split('.').reduce((a, o) => a * 256 + +o, 0);
  const mascara = p === 0 ? 0 : (0xFFFFFFFF << (32 - p)) >>> 0;
  const rede = (n & mascara) >>> 0, broadcast = (rede | ~mascara) >>> 0;
  const total = 2 ** (32 - p);
  return { rede: str(rede), broadcast: str(broadcast), mascara: str(mascara),
           hosts: p >= 31 ? (p === 31 ? 2 : 1) : total - 2 };
}

console.log(ipv4('256.1.1.1'), ipv6('2001:db8::1'));  // false true
console.log(cidrV4('192.168.1.10/24'));
// { rede: '192.168.1.0', broadcast: '192.168.1.255', mascara: '255.255.255.0', hosts: 254 }
import ipaddress

def analisar(texto: str):
    try:
        rede = ipaddress.ip_network(texto, strict=False)   # aceita IP simples, v4/v6 e CIDR
    except ValueError as e:
        return f"inválido: {e}"
    return {
        "versao": rede.version,
        "rede": str(rede),
        "primeiro": str(rede.network_address),
        "ultimo": str(rede.broadcast_address),
        "mascara": str(rede.netmask),
        # IPv4: total - 2 (rede e broadcast); /31 e /32 são casos especiais
        "hosts": rede.num_addresses - 2 if rede.version == 4 and rede.num_addresses > 2 else rede.num_addresses,
    }

print(analisar("192.168.1.10/24"))
print(analisar("256.1.1.1"))                  # inválido
print(ipaddress.ip_address("192.168.1.200") in ipaddress.ip_network("192.168.1.0/24"))  # True

ipaddress.ip_address(texto) valida um IP isolado (v4 ou v6) e rejeita zeros à esquerda.

package main

import (
	"fmt"
	"net"
	"net/netip"
)

func main() {
	// Valida um IP isolado (v4 ou v6)
	_, err := netip.ParseAddr("256.1.1.1")
	fmt.Println(err != nil) // true (inválido)

	// Valida e analisa um CIDR
	ip, rede, err := net.ParseCIDR("192.168.1.10/24")
	if err != nil {
		fmt.Println("inválido:", err)
		return
	}
	ones, bits := rede.Mask.Size()
	ultimo := make(net.IP, len(rede.IP))
	for i := range rede.IP {
		ultimo[i] = rede.IP[i] | ^rede.Mask[i]
	}
	fmt.Println("rede:", rede, "último:", ultimo, "máscara:", net.IP(rede.Mask))
	fmt.Println("total:", 1<<(bits-ones), "contém", ip, ":", rede.Contains(ip))
}
import 'dart:io';

int ipv4ParaInt(String ip) => ip.split('.').fold(0, (a, o) => a * 256 + int.parse(o));
String intParaIpv4(int n) => [24, 16, 8, 0].map((s) => (n >> s) & 255).join('.');

void main() {
  // InternetAddress.tryParse valida IPv4 e IPv6 (devolve null se inválido)
  print(InternetAddress.tryParse('256.1.1.1') != null);    // false
  print(InternetAddress.tryParse('2001:db8::1') != null);  // true

  // CIDR IPv4 manual
  final partes = '192.168.1.10/24'.split('/');
  final p = int.parse(partes[1]);
  final mascara = p == 0 ? 0 : (0xFFFFFFFF << (32 - p)) & 0xFFFFFFFF;
  final rede = ipv4ParaInt(partes[0]) & mascara;
  final broadcast = rede | (~mascara & 0xFFFFFFFF);
  print('rede ${intParaIpv4(rede)} broadcast ${intParaIpv4(broadcast)} hosts ${p >= 31 ? (p == 31 ? 2 : 1) : (1 << (32 - p)) - 2}');
}

A biblioteca padrão do Dart não tem CIDR pronto; no pub.dev há pacotes como ip_address.

public class CidrCalc {
    static boolean ipv4(String s) {
        String[] p = s.split("\\.", -1);
        if (p.length != 4) return false;
        for (String o : p) {
            if (!o.matches("0|[1-9]\\d{0,2}") || Integer.parseInt(o) > 255) return false;
        }
        return true;
    }

    static long paraLong(String ip) {
        long n = 0;
        for (String o : ip.split("\\.")) n = n * 256 + Integer.parseInt(o);
        return n;
    }

    static String paraIp(long n) {
        return ((n >> 24) & 255) + "." + ((n >> 16) & 255) + "." + ((n >> 8) & 255) + "." + (n & 255);
    }

    public static void main(String[] args) {
        String[] c = "192.168.1.10/24".split("/");
        int p = Integer.parseInt(c[1]);
        if (!ipv4(c[0]) || p < 0 || p > 32) { System.out.println("inválido"); return; }
        long mascara = p == 0 ? 0 : (0xFFFFFFFFL << (32 - p)) & 0xFFFFFFFFL;
        long rede = paraLong(c[0]) & mascara;
        long broadcast = rede | (~mascara & 0xFFFFFFFFL);
        long hosts = p >= 31 ? (p == 31 ? 2 : 1) : (1L << (32 - p)) - 2;
        System.out.println("rede " + paraIp(rede) + " broadcast " + paraIp(broadcast)
                + " máscara " + paraIp(mascara) + " hosts " + hosts);
    }
}

Não use InetAddress.getByName para validar: ele pode fazer consulta DNS. Para IPv6 use Guava (InetAddresses.isInetAddress) ou o Apache Commons InetAddressValidator.

<?php
// Valida IP isolado (v4 ou v6)
var_dump(filter_var('192.168.1.1', FILTER_VALIDATE_IP) !== false); // true
var_dump(filter_var('256.1.1.1', FILTER_VALIDATE_IP) !== false);   // false
var_dump(filter_var('2001:db8::1', FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false); // true

// CIDR IPv4
function cidrV4(string $cidr): ?array {
    $partes = explode('/', $cidr);
    if (count($partes) !== 2 || !filter_var($partes[0], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)
        || !ctype_digit($partes[1]) || (int)$partes[1] > 32) return null;
    $p = (int)$partes[1];
    $mascara = $p === 0 ? 0 : (-1 << (32 - $p)) & 0xFFFFFFFF;
    $rede = ip2long($partes[0]) & $mascara;
    $broadcast = $rede | (~$mascara & 0xFFFFFFFF);
    return ['rede' => long2ip($rede), 'broadcast' => long2ip($broadcast), 'mascara' => long2ip($mascara),
            'hosts' => $p >= 31 ? ($p === 31 ? 2 : 1) : (1 << (32 - $p)) - 2];
}

print_r(cidrV4('192.168.1.10/24'));
using System;
using System.Net;
using System.Linq;
using System.Net.Sockets;

class Program
{
    // IPAddress.TryParse é permissivo (aceita "1" como 0.0.0.1): confira também o formato
    static bool Ipv4(string s) =>
        s.Split('.').Length == 4 && IPAddress.TryParse(s, out var ip) && ip.AddressFamily == AddressFamily.InterNetwork;

    static bool Ipv6(string s) =>
        s.Contains(':') && IPAddress.TryParse(s, out var ip) && ip.AddressFamily == AddressFamily.InterNetworkV6;

    static string Str(uint n) => $"{n >> 24}.{(n >> 16) & 255}.{(n >> 8) & 255}.{n & 255}";

    static void Main()
    {
        Console.WriteLine(Ipv4("256.1.1.1") + " " + Ipv6("2001:db8::1")); // False True

        var c = "192.168.1.10/24".Split('/');
        int p = int.Parse(c[1]);
        uint ip = BitConverter.ToUInt32(IPAddress.Parse(c[0]).GetAddressBytes().Reverse().ToArray(), 0);
        uint mascara = p == 0 ? 0 : uint.MaxValue << (32 - p);
        uint rede = ip & mascara, broadcast = rede | ~mascara;
        long hosts = p >= 31 ? (p == 31 ? 2 : 1) : (1L << (32 - p)) - 2;
        Console.WriteLine($"rede {Str(rede)} broadcast {Str(broadcast)} máscara {Str(mascara)} hosts {hosts}");
    }
}

Perguntas frequentes

O que significa /24 em 192.168.1.0/24?

Que os 24 primeiros bits identificam a rede e os 8 restantes identificam os hosts. Isso equivale à máscara 255.255.255.0 e a 256 endereços (254 utilizáveis).

Por que o IP 192.168.1.10/24 mostra um aviso?

Porque o endereço tem bits de host diferentes de zero. A rede em si começa em 192.168.1.0; o cálculo usa isso, mas avisamos que o IP informado não é o início do bloco.

A ferramenta consulta algum servidor ou geolocaliza o IP?

Não. Tudo é cálculo local sobre o texto digitado, sem nenhuma consulta de rede.

Veja também

Precisa de um sistema ou app sob medida?

A VcInova desenvolve software, aplicativos e integrações para empresas de todo o Brasil.

Fale com a VcInova