Lab: CGNAT, port forward e Portr no VirtualBox¶
Laboratório para a aula sobre por que port forward não funciona atrás de CGNAT e como o Portr resolve o problema sem IP público.
Topologia¶
[Rede de casa]──bridged──[CHR-ISP]──intnet "isp-acesso"──[pfSense]──intnet "lan-cliente"──[Linux cliente]
(papel de internet) PPPoE server WAN PPPoE nginx + Portr
+ CGNAT 100.64.0.x 192.168.1.10
[VPS com IP público e domínio]──Portr server (fora do lab)
| VM | Função | vCPU | RAM | Placas |
|---|---|---|---|---|
| CHR-ISP | Provedor: PPPoE server + CGNAT | 1 | 256 MB | nic1 bridged (uplink), nic2 intnet isp-acesso |
| pfSense | Roteador do cliente | 1 | 1 GB | nic1 intnet isp-acesso (WAN), nic2 intnet lan-cliente (LAN) |
| Linux-Cliente | Servidor web atrás do CGNAT | 1 | 1 GB | nic1 intnet lan-cliente |
Endereçamento:
| Segmento | Rede | Observação |
|---|---|---|
| Uplink da CHR | DHCP da rede de casa | Faz papel de "IP público" do provedor |
| Acesso PPPoE | 100.64.0.0/24 (RFC 6598) | Gateway 100.64.0.1, assinante 100.64.0.10+ |
| LAN do cliente | 192.168.1.0/24 | pfSense 192.168.1.1, Linux 192.168.1.10 |
0. Preparação do host¶
O lab usa só VirtualBox, sem virtualização aninhada, então roda em qualquer máquina x86_64 com 8 GB de RAM ou mais. Siga a subseção do seu sistema e depois continue no passo 1.
Recursos totais do lab: 3 vCPU e cerca de 2,5 GB de RAM, mais uns 30 GB de disco.
0.1 Linux¶
Identificar a placa cabeada (usada na bridge da CHR):
Nos comandos do roteiro, troque enp5s0 pelo nome real da placa.
Só se a VM não ligar com o erro VERR_SVM_IN_USE ou VERR_VMX_IN_USE. Kernels 6.12 em diante ativam a virtualização da CPU no boot quando o módulo KVM carrega, e o VirtualBox não consegue usá-la. A correção faz o KVM ativar só quando uma VM KVM realmente liga:
# Fedora/RHEL
sudo grubby --update-kernel=ALL --args="kvm.enable_virt_at_load=0"
# Ubuntu/Debian: adicionar o mesmo parâmetro em GRUB_CMDLINE_LINUX_DEFAULT
# no /etc/default/grub e rodar: sudo update-grub
sudo reboot
O KVM continua funcionando (virt-manager, GNOME Boxes, Podman); só não dá para ter VM KVM e VM VirtualBox ligadas ao mesmo tempo. Para desfazer:
0.2 Windows¶
VBoxManage no PATH. No PowerShell:
$env:Path += ";C:\Program Files\Oracle\VirtualBox"
VBoxManage --version
mkdir "$HOME\VMs" -Force; cd "$HOME\VMs"
Nome da placa para a bridge. No Windows o nome é longo e tem espaços:
Use o nome completo entre aspas, por exemplo --bridgeadapter1 "Intel(R) Ethernet Connection I219-V".
Hyper-V e o VirtualBox. Se Hyper-V, WSL2, Docker Desktop ou "Integridade da memória" estiverem ativos, o VirtualBox roda por cima do hipervisor da Microsoft: o ícone de tartaruga verde aparece na barra da VM. Para este lab isso funciona, só fica mais lento. Não desative nada se o aluno usa WSL2 ou Docker no dia a dia. Se quiser desempenho total e aceitar que WSL2 e Docker Desktop param de funcionar até reverter, em PowerShell como administrador:
bcdedit /set hypervisorlaunchtype off
# reiniciar; para reverter: bcdedit /set hypervisorlaunchtype auto
Sintaxe. Os comandos VBoxManage do roteiro funcionam iguais no PowerShell, com duas diferenças:
- Quebra de linha é crase (
`), não barra invertida. Ou cole o comando em uma linha só. - Download, descompactação e criação de arquivos têm equivalentes próprios: veja o Apêndice A.
0.3 macOS¶
Mac com processador Intel. Funciona igual ao Linux: instale o VirtualBox, aprove a extensão da Oracle em Ajustes do Sistema > Privacidade e Segurança quando pedido, e reinicie. A placa para a bridge costuma ser en0:
Os comandos do roteiro rodam no Terminal (zsh) sem alteração, trocando enp5s0 por en0. Se o Mac só tiver Wi-Fi, a bridge pode não funcionar para a CHR; nesse caso use --nic1 nat na CHR e faça os testes de "acesso pela internet" de dentro do host com port forward do NAT do VirtualBox (Apêndice B).
Mac com Apple Silicon (M1 a M4). O VirtualBox nessas máquinas só roda sistemas ARM, e o pfSense não tem versão ARM para VM. Opções, em ordem de preferência:
- Fazer o lab numa máquina x86 (Linux ou Windows) ou numa VM x86 em nuvem com virtualização aninhada.
- Usar o UTM em modo de emulação x86 para pfSense e Linux: funciona, mas é lento. A CHR tem imagem ARM64 oficial e roda nativa no UTM.
- Assistir a aula e reproduzir só a parte do Portr, que roda nativa no macOS.
1. CHR-ISP (MikroTik RouterOS)¶
1.1 Baixar a imagem VDI oficial¶
cd ~/VMs
# versão estável atual direto do servidor de update da MikroTik
VER=$(curl -4 -s https://upgrade.mikrotik.com/routeros/NEWESTa7.stable | awk '{print $1}')
echo "Versão: $VER"
wget -4 https://download.mikrotik.com/routeros/$VER/chr-$VER.vdi.zip
unzip -o chr-$VER.vdi.zip
Se a versão vier vazia, defina na mão conforme mikrotik.com/download (ex.: VER=7.20.1).
No Windows, use o bloco equivalente do Apêndice A.
1.2 Criar a VM¶
VBoxManage createvm --name CHR-ISP --ostype Linux26_64 --register
# nic1: uplink do provedor (bridged na rede de casa)
# nic2: rede de acesso onde roda o PPPoE server
VBoxManage modifyvm CHR-ISP --cpus 1 --memory 256 --audio-enabled off \
--nic1 bridged --bridgeadapter1 enp5s0 --nictype1 virtio --nicpromisc1 allow-all \
--nic2 intnet --intnet2 isp-acesso --nictype2 virtio
VBoxManage storagectl CHR-ISP --name SATA --add sata --portcount 1
VBoxManage storageattach CHR-ISP --storagectl SATA --port 0 --device 0 --type hdd \
--medium ~/VMs/chr-$VER.vdi
VBoxManage startvm CHR-ISP
Login: admin, senha em branco. Defina uma senha no primeiro acesso.
1.3 Configurar PPPoE server e CGNAT¶
Cole no terminal da CHR:
# Nomes claros para a aula
/interface ethernet
set [find default-name=ether1] name=wan-internet
set [find default-name=ether2] name=acesso-pppoe
# Uplink recebe IP da rede de casa
/ip dhcp-client add interface=wan-internet disabled=no
# Pool de assinantes no range CGNAT (RFC 6598)
/ip pool add name=pool-cgnat ranges=100.64.0.10-100.64.0.250
# local-address = gateway do assinante; only-one impede login duplicado
/ppp profile add name=plano-cgnat local-address=100.64.0.1 remote-address=pool-cgnat \
dns-server=1.1.1.1,8.8.8.8 only-one=yes
/ppp secret add name=cliente01 password=Lab@Pppoe2026 service=pppoe profile=plano-cgnat
# max-mtu 1480 compensa o overhead do PPPoE
/interface pppoe-server server add service-name=ISP-LAB interface=acesso-pppoe \
default-profile=plano-cgnat authentication=chap,mschap2 \
max-mtu=1480 max-mru=1480 one-session-per-host=yes disabled=no
# CGNAT: todos os assinantes saem com o mesmo IP do uplink
/ip firewall nat add chain=srcnat src-address=100.64.0.0/10 out-interface=wan-internet \
action=masquerade comment="CGNAT assinantes"
# Nada entra para os assinantes a partir da internet, só retorno de conexão
/ip firewall filter
add chain=forward connection-state=established,related action=accept comment="retorno"
add chain=forward connection-state=invalid action=drop
add chain=forward in-interface=wan-internet dst-address=100.64.0.0/10 action=drop \
comment="sem entrada direta no CGNAT"
1.4 Validar¶
/ip dhcp-client print # anote o IP do uplink: será o "IP público" do provedor
/interface pppoe-server server print
/ppp secret print
Masquerade basta para a aula. CGNAT de produção usa netmap com blocos de porta por assinante e log de NAT, o que rende outra aula.
2. pfSense¶
2.1 Criar a VM¶
A ISO do Netgate Installer precisa de internet durante a instalação, por isso a WAN começa em NAT.
VBoxManage createvm --name pfSense --ostype FreeBSD_64 --register
VBoxManage modifyvm pfSense --cpus 1 --memory 1024 --audio-enabled off \
--nic1 nat --nictype1 82540EM \
--nic2 intnet --intnet2 lan-cliente --nictype2 82540EM
mkdir -p ~/VMs/pfSense
VBoxManage createmedium disk --filename ~/VMs/pfSense/pfSense.vdi --size 16384
# porta 0 = disco, porta 1 = DVD
VBoxManage storagectl pfSense --name SATA --add sata --portcount 2
VBoxManage storageattach pfSense --storagectl SATA --port 0 --device 0 --type hdd \
--medium ~/VMs/pfSense/pfSense.vdi
VBoxManage storageattach pfSense --storagectl SATA --port 1 --device 0 --type dvddrive \
--medium ~/Músicas/netgate-installer-v1.2-RELEASE-amd64.iso
# conferir antes de ligar: SATA-0-0 = vdi, SATA-1-0 = iso
VBoxManage showvminfo pfSense --machinereadable | grep '^"SATA'
VBoxManage startvm pfSense
Se aparecer "No bootable medium found" com a ISO conectada, ative EFI (VM desligada):
2.2 Instalar¶
No instalador:
- WAN:
em0, DHCP - LAN:
em1, 192.168.1.1/24 - Instalar no disco de 16 GB com as opções padrão
2.3 Remover a ISO e mover a WAN para o provedor¶
# aguardar VMState="poweroff" antes de alterar
VBoxManage controlvm pfSense acpipowerbutton
VBoxManage showvminfo pfSense --machinereadable | grep '^VMState='
VBoxManage storageattach pfSense --storagectl SATA --port 1 --device 0 --medium emptydrive
VBoxManage modifyvm pfSense --nic1 intnet --intnet1 isp-acesso
VBoxManage startvm pfSense
Com a VM ligada, a troca também funciona a quente:
2.4 Configurar a WAN em PPPoE pelo shell¶
O menu de console não tem opção de PPPoE. O script abaixo grava a configuração no config.xml via PHP do próprio pfSense e reaplica a WAN. Para não digitar no console, o VirtualBox "digita" o arquivo dentro da VM com keyboardputfile.
No Fedora, crie o arquivo:
cat > ~/VMs/pfsense-pppoe.txt <<'HOST'
sh
cat > /root/wan-pppoe.php <<'EOF'
<?php
require_once("config.inc");
require_once("interfaces.inc");
require_once("filter.inc");
require_once("util.inc");
// em0 = placa física da WAN; pppoe0 = interface lógica sobre ela
$ppp = [
"ptpid" => "0",
"type" => "pppoe",
"if" => "pppoe0",
"ports" => "em0",
"username" => "cliente01",
"password" => base64_encode("Lab@Pppoe2026"), // pfSense guarda a senha PPP em base64
"provider" => "ISP-LAB",
"mtu" => "1480",
];
config_set_path("ppps/ppp", [$ppp]);
$wan = config_get_path("interfaces/wan", []);
$wan["if"] = "pppoe0";
$wan["ipaddr"] = "pppoe";
// libera tráfego do gateway 100.64.0.1 (CGNAT) e desativa IPv6 na WAN
unset($wan["blockpriv"], $wan["blockbogons"], $wan["ipaddrv6"], $wan["dhcphostname"]);
config_set_path("interfaces/wan", $wan);
write_config("WAN PPPoE - lab CGNAT");
interface_configure("wan", true);
filter_configure_sync();
echo "PPPoE aplicado\n";
EOF
php /root/wan-pppoe.php
HOST
No Windows, crie o arquivo como no Apêndice A (seção "Arquivos para o keyboardputfile").
No console do pfSense, escolha a opção 8 (Shell). Depois, no host:
Ao final deve aparecer PPPoE aplicado.
2.5 Validar¶
No shell do pfSense:
ifconfig pppoe0 # inet 100.64.0.x --> 100.64.0.1
netstat -rn -f inet | head # default via 100.64.0.1
ping -c 3 1.1.1.1
tail -n 30 /var/log/ppp.log # negociação PPPoE, LCP e IPCP
Na CHR:
3. Linux-Cliente (servidor web atrás do CGNAT)¶
3.1 Criar a VM¶
Use Ubuntu Server (ajuste o caminho da ISO):
VBoxManage createvm --name Linux-Cliente --ostype Ubuntu_64 --register
VBoxManage modifyvm Linux-Cliente --cpus 1 --memory 1024 --audio-enabled off \
--nic1 intnet --intnet1 lan-cliente --nictype1 virtio
mkdir -p ~/VMs/Linux-Cliente
VBoxManage createmedium disk --filename ~/VMs/Linux-Cliente/disk.vdi --size 12288
VBoxManage storagectl Linux-Cliente --name SATA --add sata --portcount 2
VBoxManage storageattach Linux-Cliente --storagectl SATA --port 0 --device 0 --type hdd \
--medium ~/VMs/Linux-Cliente/disk.vdi
VBoxManage storageattach Linux-Cliente --storagectl SATA --port 1 --device 0 --type dvddrive \
--medium ~/Downloads/ubuntu-24.04-live-server-amd64.iso
VBoxManage startvm Linux-Cliente
A instalação já sai pela internet através de pfSense e CHR, então o PPPoE precisa estar ativo antes.
3.2 IP fixo¶
Confira o nome da interface com ip -br link (no VirtualBox costuma ser enp0s3):
sudo mv /etc/netplan/50-cloud-init.yaml /root/50-cloud-init.yaml.bak 2>/dev/null
sudo tee /etc/netplan/01-lab.yaml >/dev/null <<'EOF'
network:
version: 2
ethernets:
enp0s3:
addresses: [192.168.1.10/24]
routes:
- to: default
via: 192.168.1.1
nameservers:
addresses: [192.168.1.1]
EOF
sudo chmod 600 /etc/netplan/01-lab.yaml
sudo netplan apply
3.3 Servidor web¶
sudo apt update && sudo apt install -y nginx
echo "<h1>Servidor atrás do CGNAT</h1>" | sudo tee /var/www/html/index.html
curl -s http://127.0.0.1
4. Demonstração 1: port forward falhando¶
4.1 Criar o port forward no pfSense (shell)¶
Encaminha WAN TCP 8080 para 192.168.1.10:80. O associated-rule-id = pass cria a regra de NAT já liberando o tráfego, sem regra de filtro separada.
No Fedora:
cat > ~/VMs/pfsense-portfwd.txt <<'HOST'
cat > /root/portfwd.php <<'EOF'
<?php
require_once("config.inc");
require_once("filter.inc");
require_once("util.inc");
$rule = [
"source" => ["any" => ""],
"destination" => ["network" => "wanip", "port" => "8080"],
"protocol" => "tcp",
"target" => "192.168.1.10",
"local-port" => "80",
"interface" => "wan",
"descr" => "Aula CGNAT - nginx",
"associated-rule-id" => "pass",
];
$rules = config_get_path("nat/rule", []);
$rules[] = $rule;
config_set_path("nat/rule", $rules);
write_config("Port forward 8080 -> 192.168.1.10:80");
filter_configure_sync();
echo "Port forward aplicado\n";
EOF
php /root/portfwd.php
HOST
VBoxManage controlvm pfSense keyboardputfile ~/VMs/pfsense-portfwd.txt
Conferir no pfSense:
4.2 Testar "da internet"¶
Do Fedora (que está na rede de casa, do lado de fora do provedor), use o IP do uplink da CHR anotado no passo 1.4:
Pontos para mostrar aos alunos:
- O pfSense tem 100.64.0.10, não o IP "público".
- O IP público está na CHR do provedor, e o assinante não controla aquele NAT.
- O port forward no pfSense está correto, mas o pacote nunca chega até ele.
5. Demonstração 2: só o provedor consegue abrir a porta¶
Na CHR, simule o provedor vendendo "porta aberta" ou IP dedicado:
/ip firewall nat add chain=dstnat in-interface=wan-internet protocol=tcp dst-port=8080 \
action=dst-nat to-addresses=100.64.0.10 to-ports=8080 comment="porta liberada pelo provedor"
/ip firewall filter add chain=forward connection-nat-state=dstnat action=accept \
comment="libera dst-nat" place-before=[find comment="sem entrada direta no CGNAT"]
Repita o teste do Fedora:
Mensagem da aula: funciona, mas depende de o provedor configurar algo para você, e no CGNAT real a porta 8080 do IP compartilhado só pode ser de um assinante.
Remova antes da próxima demonstração:
/ip firewall nat remove [find comment="porta liberada pelo provedor"]
/ip firewall filter remove [find comment="libera dst-nat"]
6. Demonstração 3: Portr¶
O Portr é um túnel self-hosted, alternativa open source ao ngrok, que expõe serviços HTTP, TCP e WebSocket usando SSH remote port forwarding. O cliente abre a conexão de dentro para fora, então o CGNAT não interfere.
6.1 Servidor (VPS com IP público, fora do lab)¶
Requisitos:
- Domínio com registros DNS
A @eA *apontando para a VPS - Token de API da Cloudflare para o certificado wildcard (ou Route53, ou certificado próprio)
- Portas abertas: 2222 (túnel SSH), 8001, 80/443 e 30001 a 40001 (túneis TCP)
mkdir -p /opt/portr && cd /opt/portr
wget https://raw.githubusercontent.com/amalshaji/portr/main/docker-compose.prod.yaml
# chave de host do servidor de túnel
ssh-keygen -t ed25519 -f /tmp/portr_host_key -N ""
cat /tmp/portr_host_key # copiar para PORTR_SSH_HOST_KEY no .env
rm /tmp/portr_host_key /tmp/portr_host_key.pub
Arquivo .env:
PORTR_DOMAIN=tunel.seudominio.com.br
PORTR_DB_URL=postgres://postgres:SENHA_FORTE@postgres:5432/postgres
PORTR_SERVER_URL=https://tunel.seudominio.com.br
PORTR_SSH_URL=tunel.seudominio.com.br:2222
PORTR_AUTO_MIGRATE=true
PORTR_SSH_HOST_KEY= # chave PEM gerada acima
CLOUDFLARE_API_TOKEN=
POSTGRES_USER=postgres
POSTGRES_PASSWORD=SENHA_FORTE
POSTGRES_DB=postgres
O primeiro login no painel vira superusuário. Gere o token de acesso pelo painel.
6.2 Cliente (Linux-Cliente, atrás do CGNAT)¶
Instale o binário do cliente a partir das releases em github.com/amalshaji/portr e:
portr auth set --token TOKEN_DO_PAINEL --remote tunel.seudominio.com.br
portr http 80 --subdomain aula-cgnat
# publica https://aula-cgnat.tunel.seudominio.com.br
Para SSH:
Confira a sintaxe com
portr --help, o projeto está em beta e os comandos podem mudar entre versões.
6.3 Mostrar aos alunos¶
- Remova o port forward do pfSense: o Portr continua funcionando.
- Nenhuma regra de entrada no pfSense e nenhuma configuração na CHR.
- Na CHR, a conexão aparece como saída comum do assinante:
7. Comparativo para fechar a aula¶
| Abordagem | Depende do provedor | Abre porta de entrada | Custo | Uso indicado |
|---|---|---|---|---|
| Port forward no roteador | Sim, precisa de IP público | Sim | IP fixo pago | Produção com IP dedicado |
| Porta liberada pelo provedor | Sim | Sim | Variável | Raro em CGNAT |
| IPv6 | Sim, provedor precisa entregar | Sim (regra no firewall) | Zero | Quando o cliente acessa por IPv6 |
| WireGuard até VPS + dst-nat | Não | Só na VPS | VPS | Produção |
| Portr | Não | Não, conexão de saída | VPS + domínio | Desenvolvimento, webhooks, demonstrações |
Vantagens do Portr:
- Funciona atrás de CGNAT, NAT duplo e IP dinâmico.
- Sem porta de entrada no firewall do cliente, menor superfície de ataque.
- TLS automático com certificado wildcard e subdomínio por serviço.
- Self-hosted: o tráfego passa pela sua VPS, não por terceiro.
- Inspetor de requisições com replay, útil para testar webhooks.
Limitação: o projeto se declara em beta e não recomenda uso junto a servidores de produção.
8. Ordem de boot no dia da aula¶
- CHR-ISP
- pfSense (conferir
/ppp active printna CHR) - Linux-Cliente
- Portr server na VPS já rodando
9. Solução de problemas¶
| Sintoma | Causa provável | Ação |
|---|---|---|
VERR_SVM_IN_USE ao ligar VM (Linux) |
KVM ocupando a virtualização | Correção condicional do passo 0.1 |
| Tartaruga verde na VM (Windows) | VirtualBox sobre Hyper-V | Funciona, só mais lento; ver passo 0.2 |
Texto digitado errado pelo keyboardputfile |
Arquivo com CRLF ou teclado do pfSense não US | Gerar com LF (Apêndice A) e manter teclado US no console |
| Mac Apple Silicon não roda pfSense | Sem imagem ARM | Passo 0.3 |
machine is already locked |
VM ligada ou desligando | Aguardar VMState="poweroff" ou usar controlvm |
No drive attached to device slot 0 on port 1 |
Controlador SATA com uma porta só | VBoxManage storagectl pfSense --name SATA --portcount 2 |
No bootable medium found |
ISO não conectada ou firmware | Conferir grep '^"SATA' ou --firmware efi |
ppp.log só mostra PADI enviado |
CHR fora da rede isp-acesso |
VBoxManage showvminfo CHR-ISP --machinereadable \| grep intnet |
| Falha de autenticação PPP | Usuário ou senha divergentes | /ppp secret print na CHR |
| CHR não pega IP no uplink | Promiscuous mode ou Wi-Fi | --nicpromisc1 allow-all e placa cabeada |
| pfSense conecta mas não navega | Bloqueio de redes privadas na WAN | Conferir que blockpriv e blockbogons saíram do config |
| Linux sem internet | Gateway ou DNS | ip route, resolvectl status, ping 192.168.1.1 |
Apêndice A: equivalentes no Windows (PowerShell)¶
Baixar a CHR (passo 1.1)¶
cd "$HOME\VMs"
$VER = (Invoke-RestMethod https://upgrade.mikrotik.com/routeros/NEWESTa7.stable).Split(' ')[0]
"Versão: $VER"
Invoke-WebRequest "https://download.mikrotik.com/routeros/$VER/chr-$VER.vdi.zip" -OutFile "chr-$VER.vdi.zip"
Expand-Archive "chr-$VER.vdi.zip" -DestinationPath . -Force
Criar a VM da CHR (passo 1.2)¶
VBoxManage createvm --name CHR-ISP --ostype Linux26_64 --register
VBoxManage modifyvm CHR-ISP --cpus 1 --memory 256 --audio-enabled off `
--nic1 bridged --bridgeadapter1 "NOME DA SUA PLACA" --nictype1 virtio --nicpromisc1 allow-all `
--nic2 intnet --intnet2 isp-acesso --nictype2 virtio
VBoxManage storagectl CHR-ISP --name SATA --add sata --portcount 1
VBoxManage storageattach CHR-ISP --storagectl SATA --port 0 --device 0 --type hdd `
--medium "$HOME\VMs\chr-$VER.vdi"
VBoxManage startvm CHR-ISP
Os demais comandos VBoxManage seguem o mesmo padrão: troque \ no fim da linha por ` e caminhos como ~/VMs/pfSense/pfSense.vdi por "$HOME\VMs\pfSense\pfSense.vdi".
Arquivos para o keyboardputfile (passos 2.4 e 4.1)¶
O pfSense precisa receber o texto com quebras de linha Unix (LF). O bloco abaixo grava o arquivo já convertido. Cole entre @' e '@ exatamente o conteúdo que no roteiro está entre as linhas <<'HOST' e HOST (sem incluir essas duas linhas):
$script = @'
sh
cat > /root/wan-pppoe.php <<'EOF'
... conteúdo do script PHP do passo 2.4 ...
EOF
php /root/wan-pppoe.php
'@
[IO.File]::WriteAllText("$HOME\VMs\pfsense-pppoe.txt", $script.Replace("`r`n", "`n"))
VBoxManage controlvm pfSense keyboardputfile "$HOME\VMs\pfsense-pppoe.txt"
Repita o mesmo procedimento para pfsense-portfwd.txt no passo 4.1.
Testar "da internet" (passos 4.2 e 5)¶
Use curl.exe, não curl: no PowerShell, curl é apelido de outro comando.
Apêndice B: CHR em NAT (Wi-Fi ou bridge indisponível)¶
Quando a bridge não funciona (comum em Wi-Fi, principalmente no macOS), a CHR pode usar NAT do VirtualBox no uplink. O lab de PPPoE e CGNAT continua igual; muda só a forma de simular o acesso "da internet", que passa a ser um port forward do VirtualBox até a CHR.
# com a CHR desligada
VBoxManage modifyvm CHR-ISP --nic1 nat --nictype1 virtio
# porta 8080 do host vai para a porta 8080 da CHR
VBoxManage modifyvm CHR-ISP --natpf1 "aula8080,tcp,,8080,,8080"
VBoxManage startvm CHR-ISP
Nos testes dos passos 4.2 e 5, troque IP_UPLINK_DA_CHR por 127.0.0.1:
O resultado é o mesmo da bridge: timeout com só o port forward no pfSense, e resposta depois que o "provedor" faz o dst-nat na CHR.