AF_DIVERT family restored & compiling: full socket family (PF_DIVERT=32, sock_register), blocking recv/poll, divert_output-compatible sendmsg reinject, mtag type passthrough; pfk_api decls
This commit is contained in:
1 parent
fe6f767561
commit
ac56534c3b
30 files changed
+2273
-62
No files matched your search
@@ -0,0 +1,103 @@
|
||||
# Guia de arquitetura — uma página
|
||||
|
||||
English: [docs/en/guide.md](../en/guide.md).
|
||||
|
||||
## O que este port é
|
||||
|
||||
Um port fiel do **engine PF do OpenBSD 8.0** rodando dentro do **Linux
|
||||
7.3.4** como um único módulo out-of-tree, `pf.ko`. Nada é simulado: o
|
||||
casamento de regras, estado, tabelas, normalização e filas *é* o código do
|
||||
OpenBSD, compilado sob uma camada de compatibilidade; o controle vem do
|
||||
`pfctl` real, falando a ABI ioctl OpenBSD de verdade por `/dev/pf`. Existe
|
||||
**uma instância global do PF, presa a `init_net`** — exatamente como o
|
||||
OpenBSD tem um único kernel; instâncias por netns estão fora de escopo.
|
||||
|
||||
Alvos de build: fontes OpenBSD 8.0 (sha256 fixado em `VERSIONS`), Linux
|
||||
7.3.4 (`linux-7.3.4`), `gcc >= 15`, bison. O `pfvar.h` v1.548 é compartilhado
|
||||
bit a bit entre kernel e userland (codificação de ioctl em
|
||||
`module/include/pfk.h`).
|
||||
|
||||
## Componentes
|
||||
|
||||
| Caminho | Papel |
|
||||
|---|---|
|
||||
| `module/pfsrc/` | Arquivos portados do OpenBSD: `pf.c` (engine), `pf_ioctl.c` (ABI DIOC*), `pf_norm.c` (scrub/fragmentos), `pf_table.c`, `pf_ruleset.c`, `pf_if.c`, `pf_lb.c` (pools/portas NAT), `pf_osfp.c`, `pf_syncookies.c`, `ifq.c`/`hfsc.c`/`fq_codel.c` (staged para M5), `if_pflog.c` + `ip_divert.c` (referências staged), `divert_sock.c` (stub de entrada do divert), `pfk_mod.c` (load/exit, `/dev/pf`), `pfk_hooks.c` (caminho de dados netfilter) |
|
||||
| `module/compat/` | Infra Linux sob os fontes em forma BSD: shim mbuf-sobre-`sk_buff` (`pfk_mbuf`), glue de kernel (malloc/pools/timeouts/locks, `pfk_kern`), visão de interfaces e endereços (`pfk_if`), saída/forward IP com semântica BSD (`pfk_ip4`, `pfk_ip6`), busca de sockets (`pfk_pcb`), API ifq com semântica priq (`pfk_ifq`), radix/rotas/crypto portados |
|
||||
| `module/include/` | `pfk.h` (header mestre da compat + codificação `_IO*` estilo OpenBSD), `net/pfvar.h` staged, `pfk_mbuf.h`, `pfk_net.h`, `pfk_if.h` |
|
||||
| `tools/` | Build Linux do `pfctl` do OpenBSD 8.0 (binário único), relay `pdivert`, verificador de ABI (`abitest` + `make abi`), testes de parse offline (`make test`). Deltas vs upstream: `tools/UPSTREAM.md` |
|
||||
| `scripts/` | `fetch-sources.sh`, `vendorize.sh`, `stage-port.sh` (staging determinístico), `build-kernel.sh`, `build-module.sh`, automação da bancada `vm-*.sh` |
|
||||
| `tests/vm/` | Gates da suíte em VM: `01-state.sh … 04-anchors.sh` + `lib.sh`; `tests/confs/` com rulesets deployados na bancada |
|
||||
| `patches/kernel/` | Conjunto de patches de core — hoje **vazio** (`p1-needs.txt` registra por que nenhum export foi necessário); ver [patches.md](patches.md) |
|
||||
|
||||
## Caminho de dados (M2, como implementado hoje)
|
||||
|
||||
O OpenBSD roda o PF em `IPL_NET`, em contexto de processo; nossas locks da
|
||||
compat são sleepáveis, então o hook **nunca chama `pf_test()` em softirq**. O
|
||||
pacote é furtado (`NF_STOLEN`) para uma workqueue ordenada (`pfk_netisr`), o
|
||||
veredito roda em contexto de processo e é aplicado por **reinjeção**, com
|
||||
marcação por direção em `skb->mark` para que o pacotão sobrevivente não seja
|
||||
re-enfileirado pelo nosso próprio hook.
|
||||
|
||||
```
|
||||
Linux 7.3.4, módulo pf.ko
|
||||
NIC ──► netfilter (softirq — apenas enfileira)
|
||||
PRE_ROUTING PF_IN ─┐ ┌─ LOCAL_OUT PF_OUT
|
||||
POST_ROUTING PF_OUT ─┤ NF_STOLEN ├─ (roda DEPOIS do conntrack)
|
||||
LOCAL_IN/FORWARD: pass-through ┘ POST_ROUTING: NF_IP_PRI_LAST-1
|
||||
│ (ref da skb + kmalloc pfk_pkt;
|
||||
│ falha de alocação ⇒ NF_ACCEPT = fail-open)
|
||||
▼
|
||||
workqueue pfk_netisr (contexto de processo)
|
||||
│
|
||||
pfk_m_wrap_skb(skb)──► shim struct mbuf
|
||||
│
|
||||
pf_test(af, dir, ifp, &m) ◄── o engine real do OpenBSD 8.0:
|
||||
│ scrub/normalize → lookup de estado
|
||||
│ → regras/anchors/tabelas/quick
|
||||
│ → inserção de estado → veredito
|
||||
▼
|
||||
pass ──► mark |= PFK_DONE_IN/OUT ──► reinjeta: PF_IN: netif_rx() (sobrevivente
|
||||
da remontagem entra no stack)
|
||||
PF_OUT: skb_dst()->output()
|
||||
block/drop ──► kfree_skb() (+ RST/ICMP de retorno gerados pelo próprio PF)
|
||||
fragmento em buffer ──► nossa ref é liberada; pf mantém o sobrevivente (m == NULL)
|
||||
```
|
||||
|
||||
Plano de controle: `/dev/pf` (miscdev, modo 0600, escrita condicionada a
|
||||
`CAP_NET_ADMIN`) → `pfk_ioctl_io()` copia a estrutura de parâmetros usando o
|
||||
tamanho embutido na codificação `_IOR/_IOW` OpenBSD e despacha para o
|
||||
`pfioctl()` portado (`pf_ioctl.c`) — a ABI DIOC* completa, como upstream.
|
||||
`pfctl -e/-f/-s/-t` é o mesmo binário do OpenBSD, recompilado.
|
||||
|
||||
## Filas, divert, pflog — comportamento observável hoje
|
||||
|
||||
- **Filas**: o `pfctl` faz o parse de `queue`/`queue on` (sintaxe 8.0); no
|
||||
kernel a API ifq é implementada por `compat/pfk_ifq.c` com **semântica
|
||||
priq apenas**; o qdisc classful `pfq` e os back ends HFSC/FQ-CoDel chegam
|
||||
em **M5**. `ifq.c`/`hfsc.c`/`fq_codel.c` estão staged e prontos para
|
||||
compilar, mas ainda **não** estão na lista de objetos do módulo.
|
||||
- **Divert**: `divert-to`/tag `divert` produzem o veredito `PF_DIVERT` do PF;
|
||||
`divert_packet()` (`pfsrc/divert_sock.c`) hoje **descarta o pacote com um
|
||||
`pr_warn` rate-limited**, porque a família de sockets AF_DIVERT ainda não
|
||||
foi instanciada. O relay userspace `pdivert` existe e espera
|
||||
`socket(PF_DIVERT=32, SOCK_RAW, IPPROTO_DIVERT=254)`.
|
||||
- **pflog**: `pflog_packet()` retorna sucesso mas **não loga nada** (um
|
||||
único `pr_warn "packet not logged"`); `if_pflog.c` está staged, back end
|
||||
netlink em M4/M5.
|
||||
|
||||
## Milestones (status por feature em feature-matrix.md)
|
||||
|
||||
| Milestone | Escopo | Status (2026-11-11) |
|
||||
|---|---|---|
|
||||
| M0 | repo, scripts, build do kernel, VM liga com kernel próprio | concluído |
|
||||
| M1 | camada de compat, `pf.ko` carrega, `/dev/pf`, `pfctl -f`/`-s info` | concluído |
|
||||
| M2 | núcleo de filtragem: gates VM de regras/estados/tabelas/anchors | **em andamento** — caminho de dados implementado, gates 01–04 ainda não todos verdes |
|
||||
| M3 | NAT (nat/rdr/binat), scrub e2e, pflog | pendente |
|
||||
| M4 | route-to/dup-to/fail-to, divert e2e | pendente |
|
||||
| M5 | filas: back ends ifq (hfsc/fq_codel) + qdisc `pfq` | pendente |
|
||||
| M6 | docs bilíngues completas, patchset arrumado, suíte inteira verde, tags de release | em andamento (este conjunto de docs) |
|
||||
|
||||
## Próximas leituras
|
||||
|
||||
[build.md](build.md) → [vm-lab.md](vm-lab.md) → [pf-guide.md](pf-guide.md) →
|
||||
[feature-matrix.md](feature-matrix.md) → [caveats.md](caveats.md).
|
||||
Reference in new issue
Block a user