Como calcular sub-redes IPv4 e máscaras CIDR usando operadores bitwise em JavaScript puro
Quem desenvolve ferramentas de infraestrutura, dashboards de cloud (AWS VPC, Azure VNet) ou sistemas de monitoramento de redes frequentemente precisa validar se um IP pertence a uma sub-rede, calcular o endereço de broadcast ou determinar o primeiro e último host utilizável.
A maioria dos iniciantes tenta resolver isso com expressões regulares gigantescas ou vários split('.') combinados com conversões de string. Isso não só é ineficiente em termos de CPU, mas extremamente frágil.
O protocolo IPv4 é, na sua essência, um número inteiro de 32 bits não assinado (uint32). Toda a matemática de redes (máscara, rede, broadcast, range) é resolvida com elegância usando operadores binários (bitwise).
Abaixo está uma implementação limpa, modular e sem dependências externas em JavaScript puro.
1. As Duas Funções Base: Conversão de e para Inteiro 32-bit
Cada octeto do IPv4 ocupa exatamente 8 bits (1 byte). Deslocamos cada octeto para a esquerda usando o operador bitwise shift (<<):
/**
* Converte um IP em formato string ('192.168.1.50') para uint32
*/
function ipToInt(ip) {
return ip
.split('.')
.reduce((acc, octeto) => ((acc << 8) + parseInt(octeto, 10)) >>> 0, 0);
}
/**
* Converte um uint32 de volta para a notação com pontos ('192.168.1.50')
*/
function intToIp(int) {
return [
(int >>> 24) & 255,
(int >>> 16) & 255,
(int >>> 8) & 255,
int & 255
].join('.');
}
💡 Por que o operador
>>> 0?
No JavaScript, operadores bitwise padrão (<<,|,&) convertem o valor internamente para um inteiro de 32 bits com sinal (o que faria IPs que começam acima de128.0.0.0virarem números negativos). O operador Zero-fill Right Shift (>>> 0) força o interpretador V8 a tratar o número como inteiro não assinado (unsigned 32-bit).
2. A Máscara de Sub-rede a partir do CIDR
Em notação CIDR (ex: /24), o número indica quantos bits da esquerda para a direita são 1:
/**
* Gera a máscara a partir do prefixo CIDR (ex: 24 -> '255.255.255.0')
*/
function cidrToMask(cidr) {
if (cidr === 0) return 0;
return ((0xFFFFFFFF << (32 - cidr)) >>> 0);
}
3. Endereço de Rede, Broadcast e Hosts Úteis
Com os operadores lógicos bitwise:
- Endereço de Rede: Aplicação do operador
AND(&) entre o IP e a Máscara. - Endereço de Broadcast: Aplicação do operador
OR(|) entre a Rede e o inverso da Máscara (~mask).
function calcularSubrede(ipStr, cidr) {
const ip = ipToInt(ipStr);
const mask = cidrToMask(cidr);
// Endereço de Rede
const rede = (ip & mask) >>> 0;
// Endereço de Broadcast
const broadcast = (rede | (~mask >>> 0)) >>> 0;
// Quantidade total de IPs e Hosts utilizáveis
const totalIps = Math.pow(2, 32 - cidr);
let primeiroHost = null;
let ultimoHost = null;
let hostsUtilizaveis = 0;
// Tratamento de casos especiais (RFC 3021 para /31 e /32)
if (cidr === 32) {
primeiroHost = intToIp(rede);
ultimoHost = intToIp(rede);
hostsUtilizaveis = 1;
} else if (cidr === 31) {
// Links Ponto-a-Ponto sem broadcast
primeiroHost = intToIp(rede);
ultimoHost = intToIp(broadcast);
hostsUtilizaveis = 2;
} else {
primeiroHost = intToIp(rede + 1);
ultimoHost = intToIp(broadcast - 1);
hostsUtilizaveis = totalIps - 2;
}
return {
ip: ipStr,
cidr: `/${cidr}`,
mascara: intToIp(mask),
rede: intToIp(rede),
broadcast: intToIp(broadcast),
primeiroHost,
ultimoHost,
hostsUtilizaveis
};
}
4. Testando o Código
Você pode colar isso diretamente no Node.js ou no console do navegador:
console.log(calcularSubrede('192.168.10.45', 24));
Resultado:
{
"ip": "192.168.10.45",
"cidr": "/24",
"mascara": "255.255.255.0",
"rede": "192.168.10.0",
"broadcast": "192.168.10.255",
"primeiroHost": "192.168.10.1",
"ultimoHost": "192.168.10.254",
"hostsUtilizaveis": 254
}
E para checar se um IP pertence a uma determinada sub-rede em 1 linha:
function ipPertenceARede(ipTestado, rede, cidr) {
const mask = cidrToMask(cidr);
return ((ipToInt(ipTestado) & mask) >>> 0) === ((ipToInt(rede) & mask) >>> 0);
}
console.log(ipPertenceARede('10.0.5.88', '10.0.0.0', 16)); // true
console.log(ipPertenceARede('10.1.5.88', '10.0.0.0', 16)); // false
Como vocês costumam lidar com cálculos de infraestrutura de rede nas aplicações de vocês? Usam bibliotecas prontas como ipaddr.js ou funções nativas?
Calculadora visual completa de sub-redes e blocos VLSM: tecmestre.com.br/calculadora-de-redes/