RPKI: como criar ROA no Registro.br para proteger seu ASN

Quem recebe o primeiro ASN e o primeiro bloco do Registro.br costuma deixar o RPKI para depois. A sessão BGP sobe, o prefixo aparece na internet e tudo parece resolvido. O problema é que, sem uma ROA publicada, nada impede que outro AS anuncie o seu bloco e leve parte do tráfego dos seus clientes. E muitos trânsitos e IXs descartam rotas inválidas, então a ROA errada também derruba o seu próprio anúncio. Se a sessão BGP ainda é novidade, veja antes o que é BGP e como ele funciona no provedor.
Este guia mostra o caminho completo no Brasil: o que a ROA declara, como o Registro.br entrega o RPKI (modelo delegado, com uma CA própria rodando no Krill), como criar a ROA no Krill sem abrir o max-length à toa e como conferir o resultado no Routinator e em consultas públicas. Os exemplos usam o AS 64500 e blocos de documentação (203.0.113.0/24, 198.51.100.0/24 e 2001:db8::/32). Troque pelos seus.
Resposta rápida: como criar ROA no Registro.br
- Suba um Krill (a CA do RPKI da NLnet Labs) num servidor seu e crie a CA com
krillc add. - Gere o child request no Krill, cole no painel do Registro.br (TITULARIDADE, nome da organização, opção RPKI – Configurar RPKI) e traga de volta o Parent Response.
- No mesmo lugar, clique em Configurar Publicação Remota e faça a troca do repositório (Publisher Request e Repository Response).
- Crie uma ROA por prefixo que você anuncia, sem max-length maior que o prefixo, com
krillc roas update --add. - Confira no Routinator ou no RIPEstat: o seu anúncio tem de aparecer como valid.
O que é RPKI e o que uma ROA diz
RPKI (Resource Public Key Infrastructure) é uma cadeia de certificados que liga cada bloco de IP e cada ASN a quem recebeu esses recursos. No topo estão os RIRs, como o LACNIC. No Brasil, o NIC.br distribui os recursos e emite os certificados para os provedores. Com o certificado na mão, o dono do bloco assina objetos que dizem o que é legítimo no BGP.
A ROA (Route Origin Authorization) é o objeto mais usado. Ela tem três campos: o prefixo, o tamanho máximo de máscara aceito (max-length) e o ASN autorizado a originar aquele prefixo. Em português claro: “o bloco 203.0.113.0/24 pode ser anunciado pelo AS 64500, só como /24”.
A ROA não diz nada sobre o caminho. Ela valida só a origem, o último AS do AS-path. Um vazamento de rota com a origem correta continua passando. Mesmo assim, ela fecha a porta para o sequestro mais comum, em que alguém anuncia o seu bloco como se fosse dele.
Quem assina o quê na cadeia do RPKI
O validador (Routinator, por exemplo) baixa os certificados e as ROAs de todos os repositórios, confere as assinaturas desde a raiz do RIR e monta uma lista de pares prefixo, max-length e ASN. Essa lista se chama VRP (Validated ROA Payload). O roteador não fala com o RPKI direto: ele recebe os VRPs do validador pelo protocolo RTR e compara com cada rota recebida.

Hospedado ou delegado: o modelo do Registro.br
Existem duas formas de um registro entregar o RPKI. No modelo hospedado, o próprio registro gera e guarda a chave da sua CA, e você só preenche a ROA num formulário. No modelo delegado, você roda a CA. O registro assina o certificado dela, e é a sua CA que assina as ROAs e as publica.
| Modelo | Como funciona | Prós e contras | Onde aparece |
|---|---|---|---|
| Hospedado | O registro guarda a chave e você cria a ROA num formulário do portal | Mais simples; você depende do portal para tudo | Comum em RIRs como RIPE NCC e ARIN |
| Delegado | Você roda a própria CA (Krill), que recebe o certificado do registro e assina as ROAs | Mais trabalho; a chave e as ROAs ficam sob seu controle | Modelo do Registro.br para ASNs brasileiros |
O Registro.br adotou o modelo delegado e apoia o Krill como software de CA. Por isso o passo a passo tem uma etapa a mais do que nos tutoriais de RIPE ou ARIN: os dois lados trocam arquivos XML no padrão RFC 8183 antes de a primeira ROA existir. No painel do Registro.br não existe formulário de ROA: o painel só habilita o RPKI da titularidade e, se você quiser, a publicação remota. A ROA em si é criada e assinada no seu Krill.
Max-length: por que não abrir até /24 à toa
O max-length parece um atalho cômodo. Você tem um /22 e escreve uma ROA só, com max-length 24, para poder anunciar qualquer /23 ou /24 de dentro dele sem mexer no RPKI de novo. O custo aparece num ataque chamado forged-origin: o atacante anuncia um /24 seu que você não anuncia, colocando o seu ASN como origem no AS-path. A ROA aceita, o validador marca como valid e o /24 mais específico ganha do seu /22.
A RFC 9319 (BCP 185) trata exatamente disso. A recomendação é usar ROAs mínimas, que autorizam só os prefixos que você de fato anuncia, e evitar o max-length maior que o prefixo, salvo em casos bem específicos. Se você anuncia o /22 inteiro e dois /24 de engenharia de tráfego, crie três ROAs, uma para cada prefixo, todas com max-length igual à própria máscara.
E quando eu precisar anunciar um /24 numa emergência?
É o argumento mais comum a favor do max-length aberto: ataque DDoS, mitigação que exige anunciar um /24 ou divisão de tráfego às pressas. Criar a ROA do /24 leva um comando no Krill e alguns minutos até os validadores pegarem. Vale mais deixar esse comando documentado no runbook do NOC do que deixar todos os /24 do bloco autorizados o tempo todo.
Com IPv6 vale o mesmo raciocínio. Se você anuncia só o /32, a ROA é do /32. Se o plano de endereçamento prevê anunciar /48 de algum ponto da rede, crie a ROA desse /48 quando ele for para o BGP. Se a base do IPv6 ainda está confusa, comece por o que é IPv6.
Passo a passo: ativar o RPKI e criar a ROA
O roteiro abaixo segue a documentação da CLI do Krill (krillc). A interface web do Krill faz as mesmas coisas com botões; a CLI é mais fácil de documentar e de repetir. Instale o Krill pelo pacote da NLnet Labs ou por Docker, num servidor com HTTPS e com backup do diretório de dados. Perder esse diretório é perder a chave da sua CA.
1. Apontar a CLI e criar a CA
As duas variáveis evitam repetir servidor e token em todo comando. O token é o mesmo configurado no arquivo do Krill; trate-o como senha.
export KRILL_CLI_SERVER="https://localhost:3000/" export KRILL_CLI_TOKEN="troque-por-um-token-longo"
krillc add --ca meu_ca krillc show --ca meu_ca
krillc add cria a CA com o nome que você escolher (só letras, números, traço e sublinhado). krillc show mostra o estado. Logo depois de criada, ela ainda não tem nenhum recurso: quem entrega o bloco e o ASN é o Registro.br, no passo seguinte.
2. Trocar os XML com o painel do Registro.br
krillc parents request --ca meu_ca > child_request.xml
O child request é a identidade da sua CA. No painel do Registro.br, clique em TITULARIDADE e no nome da organização, desça até o fim da página e abra a opção RPKI – Configurar RPKI. Cole o conteúdo de child_request.xml no campo Child Request e clique em Habilitar RPKI. O painel devolve o Parent Response; salve como parent_response.xml.
krillc parents add --ca meu_ca --parent nicbr_ca \ --response ./parent_response.xml krillc parents statuses --ca meu_ca
O nome do pai (nicbr_ca) é só um rótulo local; use o mesmo em todos os comandos. O parents statuses confirma se a sua CA conseguiu falar com o Registro.br e se recebeu os recursos. Versões antigas do Krill usavam outra sintaxe para esse comando; se a sua recusar, rode krillc parents add --help e siga o que ela mostrar.
3. Configurar o repositório de publicação
As ROAs precisam ficar num repositório público, que os validadores do mundo inteiro consultam. O Registro.br oferece publicação remota, o que poupa você de manter um servidor rsync e RRDP. A troca é igual à anterior, com outro par de arquivos:
krillc repo request --ca meu_ca > publisher_request.xml krillc repo configure --ca meu_ca --response ./repository_response.xml krillc repo status --ca meu_ca
Gere o publisher_request.xml. Na mesma página do painel, clique em Configurar Publicação Remota, cole o conteúdo no campo Publisher Request e clique em Habilitar Publicação Remota. Salve o Repository Response como repository_response.xml.
O Krill aceita configurar pai e repositório em qualquer ordem; a página do Registro.br sugere importar primeiro o Repository Response e depois o Parent Response. O repo status deve mostrar a última publicação sem erro, e o parents statuses fica vazio enquanto o repositório não estiver configurado.
4. Criar uma ROA por prefixo anunciado
krillc roas update --ca meu_ca --add "203.0.113.0/24 => 64500" krillc roas update --ca meu_ca --add "198.51.100.0/24 => 64500" krillc roas update --ca meu_ca --add "2001:db8::/32 => 64500" krillc roas list --ca meu_ca
O formato é prefixo[-max-length] => ASN. Sem o trecho -max-length, o Krill usa a própria máscara, que é a ROA mínima recomendada. Crie uma linha para cada prefixo que sai no BGP, em IPv4 e em IPv6. O roas list no fim mostra o que está publicado.
Remover a ROA de um bloco que saiu do BGP
krillc roas update --ca meu_ca --remove "198.51.100.0/24 => 64500" krillc roas list --ca meu_ca
Bloco devolvido, cliente com ASN próprio que levou o /24 dele, prefixo que deixou de ser anunciado: tire a ROA. Uma ROA esquecida apontando para o seu ASN deixa espaço para alguém anunciar aquele prefixo com a sua origem forjada. Se o bloco passou para outro AS, a ROA certa é a do novo AS, criada por quem tem a titularidade do bloco.
Conferir a ROA no Routinator e em consultas públicas
Publicar não basta: confira como o mundo enxerga o seu prefixo. O Routinator é o validador da mesma NLnet Labs. Instalado pelo pacote oficial (antes, adicione o repositório de pacotes da NLnet Labs, como manda a página de instalação), ele já roda como serviço, com RTR na porta 3323 e HTTP na 8323, ouvindo só no localhost.
sudo apt install routinator sudo systemctl status routinator sudo journalctl --unit=routinator
O arquivo /etc/routinator/routinator.conf traz estas linhas. Para o roteador conseguir falar RTR com o validador, troque o 127.0.0.1 do rtr-listen pelo IP do servidor na rede de gerência e libere a porta só para os roteadores.
repository-dir = "/var/lib/routinator/rpki-cache" rtr-listen = ["127.0.0.1:3323"] http-listen = ["127.0.0.1:8323"]
Com o serviço rodando, a documentação pede para não usar os comandos interativos de validação na mesma máquina. Use a API HTTP. A primeira consulta pergunta se o AS 64500 pode originar o 203.0.113.0/24; a segunda testa outro ASN como origem, que deve sair invalid se a ROA estiver certa:
curl -s "http://127.0.0.1:8323/validity?asn=64500&prefix=203.0.113.0/24" curl -s "http://127.0.0.1:8323/validity?asn=64511&prefix=203.0.113.0/24"
Para uma segunda opinião de fora da sua rede, o RIPEstat tem uma consulta pública de validação RPKI. Ela usa um validador próprio e devolve o estado e as ROAs que casaram com o anúncio:
curl -s "https://stat.ripe.net/data/rpki-validation/data.json?resource=AS64500&prefix=203.0.113.0/24"
Uma saída resumida, com os valores do nosso exemplo:
"data": {
"resource": "64500",
"prefix": "203.0.113.0/24",
"validating_roas": [{"origin": "64500", "prefix": "203.0.113.0/24",
"validity": "valid", "max_length": 24}],
"status": "valid",
"validator": "routinator"
}Depois de criar a ROA, espere alguns minutos. Os validadores revisitam os repositórios em ciclos; no Routinator o padrão é a cada 10 minutos. Se em uma hora o prefixo ainda aparece como not-found, volte ao krillc repo status e ao krillc parents statuses.
Estados valid, invalid e not-found
Todo validador classifica cada par prefixo e origem em um de três estados, definidos na RFC 6811. Entender a diferença evita o erro mais caro do RPKI: criar a ROA pela metade e transformar o próprio anúncio em invalid.
| Estado | Quando acontece | O que significa na prática |
|---|---|---|
| valid | Existe ROA cobrindo o prefixo, com o mesmo ASN de origem e máscara dentro do max-length | É o que você quer ver no seu anúncio |
| invalid | Existe ROA cobrindo o prefixo, mas a origem é outro ASN ou a máscara passa do max-length | Redes com ROV descartam a rota. Se é o seu anúncio, corrija a ROA na hora |
| not-found | Nenhuma ROA cobre o prefixo | A rota passa, mas sem proteção nenhuma |
O caso clássico de invalid autoinfligido: o provedor cria a ROA do /22 com max-length 22 e, semanas depois, a equipe começa a anunciar um /24 para equilibrar dois trânsitos. O /24 agora é coberto por uma ROA que não o aceita. Antes de qualquer mudança de anúncio, a pergunta do runbook é: existe ROA para este prefixo, com esta máscara e esta origem?
Próximo passo: validar rotas no roteador (ROV)
Criar a ROA protege o seu bloco nas redes que validam. Validar as rotas que chegam até você é a outra metade, chamada ROV (Route Origin Validation). O roteador abre uma sessão RTR com o Routinator, recebe os VRPs e marca cada rota recebida dos peers como valid, invalid ou not-found. A política mais comum é descartar as invalid e preferir as valid.
A configuração muda de fabricante para fabricante e merece um post próprio. Antes de ligar o descarte, rode alguns dias só marcando as rotas e veja quantas invalid aparecem. Se você já trabalha com route-policy no Huawei, o sistema de BGP communities no Huawei mostra a estrutura em que a validação vai se encaixar. Para os comandos de consulta do dia a dia no VRP, veja a lista de comandos para roteadores e switches Huawei.
Erros comuns ao criar ROA
- ROA com o ASN errado. Bloco anunciado pelo AS do trânsito (cliente sem ASN próprio) precisa de ROA com o ASN de quem origina, não com o seu.
- Max-length aberto até /24 “por garantia”. Abre espaço para o forged-origin. Use ROA mínima.
- Esquecer o IPv6. O /32 fica not-found e não ganha a proteção que o IPv4 ganhou.
- Anunciar um /24 novo sem ROA. Se existe ROA do /22 com max-length 22, o /24 vira invalid e some das redes que fazem ROV.
- Perder ou deixar parado o servidor do Krill. O Registro.br monitora as publicações e avisa por e-mail quando estão em atraso, mas sem backup dos dados você perde a chave da CA e precisa refazer a delegação no painel.
- Deixar o Krill e o Routinator abertos para a internet. A interface do Krill e a porta RTR não precisam ficar públicas; limite por firewall.
- Não conferir depois. A ROA só está certa quando o seu anúncio aparece como valid num validador de fora.
Perguntas frequentes
Meu bloco veio do trânsito. Posso criar a ROA?
Não pela sua conta. Quem assina a ROA é o titular do bloco, ou seja, o provedor que repassou os endereços. Peça a ele uma ROA com o prefixo que você anuncia e o seu ASN como origem, e confira o resultado no RIPEstat depois.
Preciso de um Krill próprio para criar ROA no Registro.br?
Sim. O Registro.br usa o modelo delegado: o painel só habilita o RPKI, e quem assina a ROA é a sua CA. A CA indicada pelo Registro.br é o Krill. Conte com um servidor para ele, sempre no ar, e com backup dos dados.
Quanto tempo a ROA leva para aparecer nos validadores?
Normalmente minutos. Depende do ciclo de cada validador: o Routinator, por padrão, revisita os repositórios a cada 10 minutos. Se passar de uma hora, confira o status do repositório e do pai no Krill.
Qual max-length devo usar na ROA?
O mesmo tamanho do prefixo anunciado, que é o padrão quando você não informa nada no Krill. A RFC 9319 recomenda ROAs mínimas e evitar max-length maior que o prefixo, porque isso facilita o sequestro com origem forjada. Se precisar anunciar um /24 depois, crie a ROA dele na hora.
RPKI protege contra vazamento de rota?
Não por completo. A ROA valida só o AS de origem do anúncio. Um vazamento que mantém a origem correta passa pela validação. Filtros de prefixo por cliente, IRR e políticas de exportação continuam necessários.
O que acontece se eu não criar ROA nenhuma?
O seu prefixo fica not-found e continua sendo aceito, mas sem proteção contra quem anunciar o mesmo bloco com outro ASN. Você também perde a chance de ter as suas rotas preferidas em redes que dão prioridade às rotas valid.
Conclusão
Ativar o RPKI no Registro.br dá mais trabalho do que em outros registros, porque o modelo é delegado e a CA é sua. O roteiro, porém, é curto: Krill no ar, troca de XML com o painel para o pai e para o repositório, uma ROA mínima por prefixo anunciado e conferência no Routinator e no RIPEstat. Depois, toda mudança de anúncio passa a ter uma pergunta a mais no checklist: a ROA cobre este prefixo, com esta máscara e esta origem?
Com as ROAs no lugar, o passo natural é validar o que chega até a sua rede com ROV. Até lá, o seu bloco já está protegido em todas as redes que descartam rotas invalid.
Leitura recomendada: Protegendo seu ASN com RPKI, artigo da wiki do Brasil Peering Forum (CC BY-NC 4.0), que mostra a instalação do Krill e a troca de XML com o Registro.br.

[…] Quando você pede ao seu trânsito para liberar seus anúncios, ele normalmente roda algo como o bgpq4 contra o seu as-set. Quando o seu cliente pede a você, o caminho é o inverso: você gera o filtro a partir do as-set ou do ASN dele. O IRR não prova que o prefixo é seu, ele só registra o que cada um declarou. Por isso ele anda junto com o RPKI, que assina a origem com certificado; o passo a passo está no post sobre como criar ROA no Registro.br. […]
[…] tem recursos via NIC.br cria os ROAs no painel do Registro.br; o passo a passo está no guia para criar ROA para o seu bloco. Esses objetos ficam em repositórios públicos ligados à cadeia de certificados de cada […]