Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - ludarkstar99

#1
Wireguard matriz filial redundante com BGP


🔃 Roteamento Dinâmico
Status: Validado v25.7


Já vimos como configurar o roteamento estático adicionando rotas na tabela de roteamento do firewall e definindo o gateway responsável por transportar aquele tráfego. Agora vamos ver como fazer esse cenário mas usando o roteamento dinâmico, no qual a rota é negociada entre os firewalls, e geralmente é um cenário ideal para ser usado em túneis de VPN de forma redundante já que tanto o IPSec quanto o Wireguard não possuem nativamente a redundância de Túneis.

Cenário
Para exemplificar o roteamento dinâmico e demonstrar seu potencial, iremos estabelecer 2 túneis Wireguard entre 2 unidades remotas e iremos rotear o tráfego com alta disponibilidade, de forma que se cair um dos túneis, haverá uma convergência do tráfego para o segundo túnel disponível.

Premissas
1. Matriz possui 2 Links de internet com IPs públicos;
2. Matriz será o lado servidor da conexão, ou seja, apenas recebe conexões vindas da filial.
3. Filial pode possuir links dinâmicos ou estar atrás de CGNAT.
4. LAN da Matriz: 192.168.1.0/24.
5. LAN da Filial: 192.168.2.0/24.
6. Será usado iBGP, ou seja, apenas troca de rotas entre 2 peers diretamente conectados.
7. Serão negociadas apenas as redes LAN de cada peer/firewall.


Configurando os Túneis Wireguard

No Firewall Matriz

Acesse o menu VPN → Wireguard → Instances.
  Marque a caixa Enable Wireguard e clique em Apply.

  Clique em "+ Add" para adicionar uma nova instância.
  Marque a opção Advanced mode no topo da tela.
  Preencha o nome da instância com Tunel-Matriz-Filial-A
  Clique no ícone da engrenagem a frente de Public key para gerar o par de chaves pública/privada.
  Preencha Listen port com 51820.
  Preencha o Tunnel Address com 192.168.66.1/30
  Marque a opção Disable routes.
  Preencha o campo gateway com 192.168.66.2
  Clique em Save.

  Clique em "+ Add" para adicionar uma nova instância.
  Marque a opção Advanced mode no topo da tela.
  Preencha o nome da instância com Tunel-Matriz-Filial-B
  Clique no ícone da engrenagem a frente de Public key para gerar o par de chaves pública/privada.
  Preencha Listen port com 51821.
  Preencha o Tunnel Address com 192.168.67.1/30
  Marque a opção Disable routes.
  Preencha o campo gateway com 192.168.67.2
  Clique em Save.
  Clique em Apply.


No Firewall Filial

Acesse o menu VPN → Wireguard → Instances.
  Marque a caixa Enable Wireguard e clique em Apply.
 
  Clique em "+ Add" para adicionar uma nova instância.
  Marque a opção Advanced mode no topo da tela.
  Preencha o nome da instância com Tunel-Matriz-Filial-A
  Clique no ícone da engrenagem a frente de Public key para gerar o par de chaves pública/privada.
  Preencha Listen port com 51820.
  Preencha o Tunnel Address com 192.168.66.2/30
  Marque a opção Disable routes.
  Preencha o campo gateway com 192.168.66.1
  Clique em Save.

  Clique em "+ Add" para adicionar uma nova instância.
  Marque a opção Advanced mode no topo da tela.
  Preencha o nome da instância com Tunel-Matriz-Filial-B
  Clique no ícone da engrenagem a frente de Public key para gerar o par de chaves pública/privada.
  Preencha Listen port com 51821.
  Preencha o Tunnel Address com 192.168.67.2/30
  Marque a opção Disable routes.
  Preencha o campo gateway com 192.168.67.1
  Clique em Save.
  Clique em Apply.




Configurando os Peers Wireguard

No Firewall Matriz

Acesse o menu VPN → Wireguard → Peers.
  Clique em "+ Add" para adicionar um novo Peer.
  Preencha o nome da instância com Tunel-Matriz-Filial-A
  Copie a chave Pública gerada na Instância "Tunel-Matriz-Filial-A" do *Firewall da Filial* e cole no campo Public Key.
  Preencha Allowed IPs com 0.0.0.0/0.
  Deixe os campos "Endpoint Address" e "Endpoint port" vazios.
  No campo Instances selecione a Instância Tunel-Matriz-Filial-A.
  Em Keepalive interval insira 10.
  Clique em Save.
 
  Clique em "+ Add" para adicionar um novo Peer.
  Preencha o nome da instância com Tunel-Matriz-Filial-B
  Copie a chave Pública gerada na Instância "Tunel-Matriz-Filial-B" do *Firewall da Filial* e cole no campo Public Key.
  Preencha Allowed IPs com 0.0.0.0/0.
  Deixe os campos "Endpoint Address" e "Endpoint port" vazios.
  No campo Instances selecione a Instância Tunel-Matriz-Filial-B.
  Em Keepalive interval insira 10.
  Clique em Save.
  Clique em Apply.


No Firewall da Filial

Acesse o menu VPN → Wireguard → Peers.
  Clique em "+ Add" para adicionar um novo Peer.
  Preencha o nome da instância com Tunel-Matriz-Filial-A
  Copie a chave Pública gerada na Instância "Tunel-Matriz-Filial-A" do *Firewall da Matriz* e cole no campo Public Key.
  Preencha Allowed IPs com 0.0.0.0/0.
  Em Endpoint Address preencha com o primeiro IP Público da Matriz.
  Preencha o Endpoint port com 51820.
  No campo Instances selecione a Instância Tunel-Matriz-Filial-A.
  Em Keepalive interval insira 10.
  Clique em Save.
 
  Clique em "+ Add" para adicionar um novo Peer.
  Preencha o nome da instância com Tunel-Matriz-Filial-B
  Copie a chave Pública gerada na Instância "Tunel-Matriz-Filial-B" do *Firewall da Matriz* e cole no campo Public Key.
  Preencha Allowed IPs com 0.0.0.0/0.
  Em Endpoint Address preencha com o segundo IP Público da Matriz.
  Preencha o Endpoint port com 51821.
  No campo Instances selecione a Instância Tunel-Matriz-Filial-B.
  Em Keepalive interval insira 10.
  Clique em Save.
  Clique em Apply.


Configurando as Regras de Firewall

No Firewall Matriz

Acesse o menu Firewall → Rules → WAN1.
  Clique em "+ Add" para adicionar uma nova Regra para liberar a conexão VPN.
  Em protocolo selecione UDP.
  Em Destination selecione This Firewall
  Em Destination Port Range selecione Other e preencha o campo From com 51820 e o campo To com 51820
  Marque a caixa Log.
  Insira a seguinte descrição: Libera VPN Wireguard
  Clique em Save
  Clique em Apply changes.

Acesse o menu Firewall → Rules → WAN2.
  Clique em "+ Add" para adicionar uma nova Regra para liberar a conexão VPN (no segundo link).
  Em protocolo selecione UDP.
  Em Destination selecione This Firewall
  Em Destination Port Range selecione Other e preencha o campo From com 51821 e o campo To com 51821
  Marque a caixa Log.
  Insira a seguinte descrição: Libera VPN Wireguard
  Clique em Save
  Clique em Apply changes.

Acesse o menu Firewall → Rules → Wireguard (Group).
  Clique em "+ Add" para adicionar uma nova Regra para liberar o tráfego dentro do túnel.
  Marque a caixa Log.
  Insira a seguinte descrição: Libera Trafego VPN Wireguard
  Clique em Save
  Clique em Apply changes.


No Firewall da Filial

Acesse o menu Firewall → Rules → Wireguard (Group).
  Clique em "+ Add" para adicionar uma nova Regra para liberar o tráfego dentro do túnel.
  Marque a caixa Log.
  Insira a seguinte descrição: Libera Trafego VPN Wireguard
  Clique em Save
  Clique em Apply changes.




Verificando os Túneis

No Firewall Matriz

Acesse o menu VPN→ Wireguard→ Status.
Verifique se todos os túneis foram conectados com sucesso como na imagem abaixo (coluna status verdinha).

Caso alguma das conexões não tenha sido estabelecida (ícone vermelho), reveja as etapas acima novamente. Verifique se ambos os firewalls consegue se comunicar por ambos os links de internet.



Instalando Plugin OS-FRR para Roteamento Dinâmico

Em ambos os Firewalls

  Navegue até System → Firmware → Plugins.
  Localize e instale o plugin os-frr
  Atualize a página para aparecer o menu "Routing"


Habilitando o Roteamento Dinâmico

Em ambos os Firewalls

  Navegue até Routing → General.
  Marque a opção Enable para habilitar o roteamento dinâmico.
  Clique em Apply.


Configurando o Roteamento Dinâmico

No Firewall Matriz

Habilite o BGP
  Acesse o menu Routing → BGP.
  Marque a opção Enable.
  Preencha o campo Network com a rede LAN da matriz, no formato CIDR. Exemplo: 192.168.1.0/24.
  Clique em Apply.

Cadastre os Vizinhos BGP
  Acesse a guia Neighbors
  Clique em "+ Add" para adicionar um novo vizinho BGP.
  Preencha o campo description com: Tunel-Matriz-Filial-A
  Em Peer-IP preencha o endereço 192.168.66.2
  Em Remote AS preencha 65551
  Marque a opção BFD.
  Marque a opção Advanced mode no canto superior esquerdo do formulário.
  Preencha o campo Weight (peso desta rota) com 500.
  Clique em Save.

  Clique em "+ Add" para adicionar um novo vizinho BGP.
  Preencha o campo description com: Tunel-Matriz-Filial-B
  Em Peer-IP preencha o endereço 192.168.67.2
  Em Remote AS preencha 65551
  Marque a opção BFD.
  Clique em Save.
  Clique em Apply.

Habilite o BFD
  Acesse o menu Routing → BFD.
  Marque a opção Enable.
  Clique em Apply.


No Firewall da Filial

Habilite o BGP
  Acesse o menu Routing → BGP.
  Marque a opção Enable.
  Preencha o campo Network com a rede LAN da filial, no formato CIDR. Exemplo: 192.168.2.0/24.
  Clique em Apply.

Cadastre os Vizinhos BGP
  Acesse a guia Neighbors
  Clique em "+ Add" para adicionar um novo vizinho BGP.
  Preencha o campo description com: Tunel-Matriz-Filial-A
  Em Peer-IP preencha o endereço 192.168.66.1
  Em Remote AS preencha 65551
  Marque a opção BFD.
  Marque a opção Advanced mode no canto superior esquerdo do formulário.
  Preencha o campo Weight (peso desta rota) com 500.
  Clique em Save.

Clique em "+ Add" para adicionar um novo vizinho BGP.
  Preencha o campo description com: Tunel-Matriz-Filial-B
  Em Peer-IP preencha o endereço 192.168.67.1
  Em Remote AS preencha 65551
  Marque a opção BFD.
  Clique em Save.
  Clique em Apply.

Habilite o BFD
  Acesse o menu Routing → BFD.
  Marque a opção Enable.
  Clique em Apply.


Verificando a Configuração

Em Ambos os Firewalls

Acesse o menu Routing → Diagnostics → General.
Acesse a guia Running Configuration.
Verifique se há configuração correspondente (seções router-bgp e address-family).
Caso não tenha carregado a configuração, tente rever todo o processo para garantir que não deixou nenhuma etapa de fora da configuração.



Validando a Comunicação

Para validar a comunicação de rede entre as unidades, use um computador de cada unidade e dispare um PING entre eles.
Não se esqueça que deverá haver regras na interface LAN de cada firewall, permitindo a rede LAN local comunicar com a rede LAN remota.
Use o `tracert` para garantir que a rota está saindo pelo túnel VPN ao invés de um link de internet específico definido através de Policy Routing (gateway explícito em regras da LAN).



Qual Túnel Está sendo Usado Preferencialmente?

No firewall da Matriz

Acesse o menu Routing → Diagnostics → BGP
Podemos ver que a melhor rota para a rede da Filial é o túnel que definimos um peso (Weight) de 500. Portante este é o túnel sendo utilizado.


#2
Virtual private networks / Re: VPN Site-to-Site + LDAP
November 28, 2025, 05:07:14 AM
Olá John. seja bem vindo ao fórum do OPNsense.
Vai usar OPNsense nas duas pontas?
IP fixo em ambas as pontas?
Conexões de Internet redundantes?

De forma geral, recomendo usar wireguard roteado, com túneis redundantes e roteamento dinâmico (bgp) para alta disponibilidade do túneis.
Também pode aproveitar o bgp e enviar a rota/prefixo 0.0.0.0/0 para a filial.
Não esquece de criar um NAT de saída na matriz, mascarando os endereços de origem da filial ao saírem pelo(s) links de internet.

Tenho o procedimento do wireguard/bgp. se quiser, envia o teu e-mail no pv que envio o procedimento.
#3
Hi,

This issue is due to code incompatibility, as the core has undergone changes in how it handles runtime model fields.

For now, instead of using the Capitole URL that provides the full set of categories, we must insert them one by one using the links available at:
https://dsi.ut-capitole.fr/blacklists/download/

just register the ones you want to block.
#4
We accomplished that by adding a static route with the endpoint as the target/32 and associating the corresponding gateway.
Another scenario we have (for failover purposes) is to use two tunnels with BGP to weight the preferred path.
#5
Olá,

Após atualização para a versão 25.1.x, passamos a receber o erro abaixo em alguns firewalls:
[16-Mar-2025 11:41:18 UTC] PHP Warning:  PHP Startup: Unable to load dynamic library 'mongodb.so' (tried: /usr/local/lib/php/20230831/mongodb.so (Cannot open "/usr/local/lib/php/20230831/mongodb.so"), /usr/local/lib/php/20230831/mongodb.so.so (Cannot open "/usr/local/lib/php/20230831/mongodb.so.so")) in Unknown on line 0


O erro é corrigido logando via ssh no firewall e rodando o comando para remover a biblioteca php/mongo que erroneamente não está em uso:
pkg install -y php83-pecl-mongodb-1.19.0


Update: Para a versão 25.1.7 usar o comando abaixo:
pkg install -y php83-pecl-mongodb-1.21.0

#6
Olá Pipe!
Calma, não criemos pânico! hehehe
Sei bem como é, já passei uns perrengues assim.
Mas desde que passei a trabalhar com um fornecedor bacana e com appliances validados, tenho usado menos gadernal.

Primeira coisa, tu tá usando realtek. Arranca fora. Sem mais nem menos. Não importa que tenha alterado a atribuição (assignment) da lan para a placa Intel, a realtek continua lá.
Não importa que tenha instalado o driver novo via os-realtek... se algo tem a chance de dar errado, vai dar errado.

Pra gente te ajudar, tu vai ter que dar detalhes.
Qual a versão do opnsense antes?
Qual o hardware?
Quais funções habilitadas?
Gerou algum log ou stacktrace? (bolinha laranja que fica acesa no canto superior da tela antes da caixa de pesquisa.

Esse cenário que mencionou é típico de incompatibilidade de drivers. Aposto que instalou outro firewall baseado em linux, e aí estabilizou. linux funciona melhor com realtek.

Outra coisa. Versão 25.1 acabou de sair. Volta pro barco até estar estável, fica na 24.1 ou 24.7.
É só olhar aqui no fórum que vai ver uma lista grande de problemas com a 25.1:

https://forum.opnsense.org/index.php?topic=45842.msg229386#msg229386
[...]


#7
Olá Pipe,
É possível sim.
No firewall matriz ao cadastrar o Peer referenciando a filial, no campo "Allowed IPs" você preenche com o endereço IP de túnel da Filial, ex.: 10.9.0.2/32 e também com os hosts da filial na qual a matriz terá acesso. ex.: 172.16.0.10/32 172.16.0.15/32 (hosts na lan filial).
#8
DIRECTOR CUT
TL;DR;

Resumindo, a partir da versão 24.7.3, para pesquisar múltiplos termos na caixa de pesquisa, como no exemplo de usuário autenticado na vpn, ficariam assim:
filtro: "ludarkstar99 Peer Connection Initiated".

*sem as aspas é claro.
Lembrando que Só haverá resultado se todas as palavras forem encontradas dentro da linha do log.



Olá,
espero que estejam todos bem.

Hoje pretendo falar sobre algo que me revira a cabeça, a lá Roberta Miranda. e é sobre LOGS.
Mais especificamente sobre pesquisa em LOGS.
Você já tentou pesquisar algo nos logs da VPN, como achar as datas de autenticações de um determinado usuário, ou mesmo procurar uma conexão presa através da tela de states (ou sessions)? Então você já deve ter se perguntado, como preencher a abençoada caixinha de pesquisa para filtrar "da melhor maneira" e trazer os dados na tela com um filtro apurado para encontrar rapidamente o que procura.
Pois bem, como diria um famoso youtuber (de mala e cuia): "Vem comigo!"

PARA COMEÇAR TEM QUE COMEÇAR DO COMEÇO
Eu pretendo lhe mostrar como funciona a pesquisa, e que lhe sirva de futuras referências quando precisar investigar esse tipo de problema. Eu precisei e ninguém me explicou como fazer, então estou deixando o rastro pra você não falar que ninguém te ajudou. A faca tá aí, corta o queijo quem quer!
Primeiro vamos ver como era a pesquisa em um firewall rodando a versão "OPNsense 24.1", sim, tem que ver o passado pra encarar o futuro. Larga de ser preguicinha e vai estudar rapaz...
Acessando o menu "VPN > OpenVPN > Log File" você é apresentado a tela de consulta aos logs mais recentes do openvpn. Esta tela apresenta uma listagem paginada dos logs, e se olhar no canto superior direito, vai ver que tem uma barrinha de pesquisa para procurar informações em específico. Tente conectar na VPN e voltar nesta tela e pesquisar pelo seu login de conexão openvpn. Não esqueça de marcar o nível de severidade como DEBUG para vermos todas as mensagens. Você verá que irá listar as entradas de log que contém o teu login. Até aí perfeito.

Date   Severity   Process   Line
2025-02-19T20:41:27-03:00   Notice   openvpn_server4   ludarkstar99/177.177.177.177:51645 SIGUSR1[soft,ping-restart] received, client-instance restarting
2025-02-19T20:41:27-03:00   Notice   openvpn_server4   ludarkstar99/177.177.177.177:51645 [ludarkstar99] Inactivity timeout (--ping-restart), restarting
2025-02-19T08:16:14-03:00   Notice   openvpn_server4   ludarkstar99/177.177.177.177:51645 Protocol options: protocol-flags cc-exit tls-ekm dyn-tls-crypt

Agora, vamos supor que você está buscando fazer uma auditoria nos acessos do ludarkstar99. Apenas filtrar pelo login do usuário vai trazer diversas mensagens (assumindo que está usando nível de log 3/4 no openvpn) e que não são exatamente do login. Algumas sobre inatividade, outras sobre criptografia ou mesmo certificado. E se você quiser trazer apenas as linhas de log de autenticação?
Bom então vamos atrás do filtro. Primeiro você precisa encontrar uma linha modelo. Desconecte e conecte na vpn novamente, atualize a tela rapidamente e irá conseguir localizar uma linha com o texto abaixo, indicando uma autenticação bem sucedida:
177.177.177.177:51645 [ludarkstar99] Peer Connection Initiated with [AF_INET6]::ffff:177.177.239.204:51645 (via 177.39.39.39%vmx0_vlan301)

Vamos dizer que você queira pesquisar os logins bem sucedidos. Então joga na caixa de pesquisa o termo "Peer Connection Initiated with". Logo virá o login de todos os usuários na VPN e não somente o usuário que você está buscando. Você deve estar pensando - é fácil, é só colocar o nome do usuário entre colchetes seguido da frase de conexão bem sucedida como em "[ludarkstar99] Peer Connection Initiated with". Tente aí então espertão, e verá que não trará resultado nenhum! Isso basicamente ocorre porque o opnsense substitui caracteres especiais como "+&$()[]" dentre vários outros. Então... como filtrar tanto pelo nome do usuário junto da frase ou termo que indica um login bem sucedido?
Santa Barbatana Batman! Como não pensei nisso antes. Se é pesquisa de logs, deve haver algum tipo de expressão regular, ou caracteres curingas, geralmente sempre tem! Pois bem. e realmente tem, mas não é tão simples assim.


OS PRUDENTES VEEM O PERIGO E SE ABRIGAM, MAS OS SIMPLES SEGUEM ADIANTE E PAGAM O PREÇO.
Sempre que algo ocorre, seja no trabalho ou durante as aulas que ministro, sempre paro, respiro fundo e digo a mim mesmo: Eu amo problemas! Problemas me fazem crescer! Quer uma frase mais inspiradora que essa? "Problema bom é problema resolvido".
Se eu simplesmente te entregasse o ouro, como um belo índio de cabelos negros e lisos, você faria como os portugueses, iria embora sem nem me dar um espelho.
Ao invés disso vamos malhar o cérebro um pouco.
Quero que você entenda como ocorre esse filtro dos logs e para isso precisaremos inspecionar desde a requisição do navegador com o filtro, até o momento que o opnsense consulta as linhas do log e verifica se há uma correspondência do filtro ou não.
Abra as ferramentas de desenvolvedor do navegador (control+F12 ou control+shift+i) e clique na guia Rede.
Agora volte no campo de pesquisa e digite o nome do usuário da vpn + o termo de login bem sucedido: exemplo: [ludarkstar99] Peer Connection Initiated.
Você verá na guia de captura de requisições de rede, que houve uma requisição para a URL "/api/diagnostics/log/core/openvpn" e que foram passados alguns parametros searchPhrase e severity. SearchPhrase contém as palavras pesquisadas e severity os níveis de log para corresponder.
Agora, quando o servidor web recebe essa requisição, o código php vai rotear para uma controller que está associada a API.
Em específico, para sermos breve, será usado a controller "/usr/local/opnsense/mvc/app/controllers/OPNsense/Diagnostics/Api/LogController.php".

Você pode ver o código que remove os caracteres especiais na seguinte seção:
CodeSelect
// create filter to sanitize input data
        $filter = new Filter([
            'query' => function ($value) {
                return preg_replace("/[^0-9,a-z,A-Z, ,*,\-,_,.,\#,\:]/", "", $value);
            }
        ]);


Ou seja, só serão aceitos na pesquisa os caracteres: De a-z maiúsculas e minúsculas, números, e espaço.

Seguindo a lógico do código, essa função limita em 9999 a quantidade de linhas para não estourar a memória e em seguida chama o configd para executar a ação:
"system diag log" passando como parâmetros os termos de pesquisa, módulo (core), arquivo (openvpn) além das severities.

Bom, agora temos que saber o que o configd vai executar com esse comando, e agora vamos precisar consultar o arquivo "/usr/local/opnsense/service/conf/actions.d/actions_system.conf", no qual possui a definição da ação "diag log" conforme podemos ver abaixo.

CodeSelect
[diag.log]
command:/usr/local/opnsense/scripts/syslog/queryLog.py
parameters:--limit %s --offset %s --filter %s  --module %s --filename %s --severity %s
type:script_output
message:Show log

Pimba!

O configd está apenas chamando outro script (queryLog.py) e repassando os parâmetros para ele. Inclusive, podemos nós mesmos chamar o script python manualmente da seguinte forma:
CodeSelect
/usr/local/opnsense/scripts/syslog/queryLog.py --limit 10 --offset 0 --filter "ludarkstar99"  --module core --filename openvpn --severity ""

Pimba novamente!

A saída é um json contendo a linha do log com os metadados da pesquisa realizada:
CodeSelect
{"filters":"ludarkstar99","rows":[{"timestamp":"2025-02-20T00:15:39-03:00","parser":"SysLogFormatRFC5424","facility":3,"severity":"Notice","process_name":"openvpn_server4","pid":"703","rnum":3798,"line":" ludarkstar99\/177.177.177.177:64451 Protocol options: protocol-flags cc-exit tls-ekm dyn-tls-crypt"},....
[...SAÍDA OMITIDA...]

Nadamos, nadamos... E ainda não descobrimos como é feito o filtro.
Calma jovem padawan, já estamos em 99% aqui. segue o baile.

Vamos abrir o arquivo que faz a consulta bruta ao log, /usr/local/opnsense/scripts/syslog/queryLog.py.

Aqui já podemos ver mais um pouco sobre o que representa cada argumento do script:
CodeSelect
if __name__ == '__main__':
    # handle parameters
    parser = argparse.ArgumentParser()
    parser.add_argument('--output', help='output type [json/text]', default='json')
    parser.add_argument('--filter', help='filter results', default='')
    parser.add_argument('--limit', help='limit number of results', default='')
    parser.add_argument('--offset', help='begin at row number', default='')
    parser.add_argument('--filename', help='log file name (excluding .log extension)', default='')
    parser.add_argument('--module', help='module', default='core')
    parser.add_argument('--severity', help='comma separated list of severities', default='')
    inputargs = parser.parse_args()


Logo mais abaixo vemos a lógica para abrir o(s) arquivo(s) de log.
CodeSelect
    if inputargs.filename != "":
        log_filenames = list()
        if inputargs.module == 'core':
            log_basename = "/var/log/%s" % os.path.basename(inputargs.filename)
        else:
            log_basename = "/var/log/%s/%s" % (
                os.path.basename(inputargs.module), os.path.basename(inputargs.filename)
            )
        if os.path.isdir(log_basename):
            # new syslog-ng local targets use an extra directory level
            filenames = glob.glob("%s/%s_*.log" % (log_basename, log_basename.split('/')[-1].split('.')[0]))
            for filename in sorted(filenames, reverse=True):
                log_filenames.append(filename)


Aqui temos o ouro, as linhas relacionadas a correpondencia do filtro no texto. Repare que é usado expressão regular.
O que acontece aqui é o seguinte:
1. Seu filtro de pesquisa tem o caractere * substituído por .* (expressão regular que identificar qualquer caractere 0 ou mais vezes;
2. Se não houver o caractere curinga na sua pesquisa (*), seu filtro vai ser forçado a virar uma expressão regular, com .* antes da(s) palavra(s) e depois;
3. O Script lê cada linha dos logs e verifica se a expressão regular corresponde com o texto da linha.

Aqui podemos ver as partes informadas acima:

CodeSelect
[...]
        try:
            filter = inputargs.filter.replace('*', '.*').lower()
            if filter.find('*') == -1:
                # no wildcard operator, assume partial match
                filter = ".*%s.*" % filter
            filter_regexp = re.compile(filter)
        except re.error:
            # remove illegal expression
            filter_regexp = re.compile('.*')

        row_number = 0
        for filename in log_filenames:
            if os.path.exists(filename):
                format_container = FormatContainer(filename)
                for rec in reverse_log_reader(filename):
                    row_number += 1
                    if rec['line'] != "" and filter_regexp.match(('%s' % rec['line']).lower()):
[...]

Detalhe sórdido que o script vai ler todos os arquivos da pasta /var/log/openvpn/* até atingir o limite de linhas (9999 caso não especificado).


Então podemos tirar as seguintes conclusões:
Para pesquisar na versão 24.7.2 ou anterior do opnsense, você pode usar o caractere curinga * sim, mas tem um formato especial para usá-lo.
Exemplo de filtro: *ludarkstar99*Peer Connection Initiated

Basicamente você coloca um * antes do texto, e um * entre palavras que há caracteres ou termos desconhecidos, então o curinga faz seu papel de curinga (wildcard).

E se você perguntar: luciano, não bastaria colocar ludarkstar*Peer ? tem mesmo que botar o * antes do texto? Tem sim meu jovem, isso ocorre por conta que antes do nome do usuário tem outros caracteres, como data/hora, nome do processo, e tal. Se a linha do log começasse com ludarkstar99, aí sim iria funcionar, mas não é assim que começa e você agora sabe exatamente o porque.


AS COISAS VELHAS JÁ PASSARAM, EIS QUE TUDO SE FEZ NOVO.
Certo. Entendemos o rolê que é fazer uma simples pesquisa no OPNsense 24.1, e aí eu fui tentar em outro firewall com a versão 24.7.12 e não deu certo...
Sabe porque não deu certo? Porque D'us quis! Talvez ele só ame quem lê e carrega seu código.

Mas se eu puder ajudar em algo, fica a dica, leia o código. As tábuas com os 10 mandamentos não foram feitas atoa...

A partir da versão 24.7.3 foi alterado o código que faz a correspondência de filtros no log.
Abrindo o mesmo arquivo /usr/local/opnsense/scripts/syslog/queryLog.py na versão 24.7, vemos que foi criado uma classe específica para esta função - LogMatcher conforme o trecho de código abaixo.

CodeSelect
[...]
from log_matcher import LogMatcher
[...]
log_matcher = LogMatcher(inputargs.filter, inputargs.filename, inputargs.module, inputargs.severity)
        for record in log_matcher.match_records():
[...]

Dá pra ver que alguém entendeu o domínio da questão e encapsulou a complexidade do código. E como ainda estamos em busca das tábuas perdidas, vamos precisar investigar abrindo o arquivo que contém a definição da classe LogMatcher.

Abrindo o arquivo /usr/local/opnsense/scripts/syslog/log_matcher.py podemos ver a implementação do filtro na versão 24.7, e a lógica ainda é a mesma. Checa se a linha tem correspondência via regex com o termo de pesquisa. Seu texto da caixinha de pesquisa é tratado como uma coisa só, por isso a necessidade de usar curingas (*) para dizer que tem algo entre as palavras pesquisadas.

CodeSelect 
    if line != "" and self.filter_regexp.match(('%s' % line).lower()):
        record = self.parse_line(line, format_container)
        if len(self.severity) == 0 or record['severity'] is None or record['severity'] in self.severity:
            yield record



Já na versão 24.7.3, podemos ver que foi completamente alterado a forma de pesquisar. Agora ao invés de usar a correspondência via expressão regular, passou a ser usado a função find (linha tmp.find abaixo) que nada mais é que uma busca por termos literais. Então nada de * mais nas pesquisas. Além disso, o código quebra cada palavra para pesquisá-la individualmente e só retorna correspondência se todos os tokens (palavras individuais) forem encontradas na linha do log.

CodeSelect

    def _match_line(self, line):
        # matcher, checks if all clauses are matched.
        tmp = line.lower()
        for clause in self.filter_clauses:
            if tmp.find(clause) == -1:
                return False

        return line != ''


Resumindo, até a versão 24.7.2 se fossemos pesquisar as conexões vpn para um determinado usuário, iríamos filtrar da seguinte forma:
filtro: "*ludarkstar99*Peer Connection Initiated".

A partir da versão 24.7.3, para pesquisar múltiplos termos na caixa de pesquisa, como no exemplo de usuário autenticado na vpn, ficariam assim:
filtro: "ludarkstar99 Peer Connection Initiated".

*sem as aspas é claro.
Lembrando que para a versão 24.7.3+ Só haverá resultado se todas as palavras forem encontradas dentro da linha do log.
#9
Olá, pessoal!

Espero que estejam todos bem. Hoje vou falar sobre algo que sempre me deixa intrigado: Logs. Mais especificamente, pesquisa em logs
Se você já precisou verificar as datas de autenticações de um usuário no log da VPN ou rastrear uma sessão "presa" na tela de states/sessions, deve ter se perguntado qual seria a melhor maneira de preencher a caixa de pesquisa para filtrar e encontrar rapidamente o que procura. 

Pois bem, como diria um famoso youtuber: "Vem comigo!"



COMEÇANDO PELO COMEÇO

A ideia é mostrar como funciona a pesquisa no OPNsense, para que isso possa servir de referência em futuras investigações. Precisei desse conhecimento e quase ninguém explicou como fazer. Então, deixo aqui o rastro para você não dizer que ninguém te ajudou.

Primeiro, vamos conferir como era a pesquisa em um firewall com a versão "OPNsense 24.1". É importante entender o passado para encarar o futuro. 

  • Acesse VPN > OpenVPN > Log File.
  • Na tela, você verá os logs mais recentes do OpenVPN em formato paginado.
  • No canto superior direito, há uma barra de pesquisa para filtrar informações específicas.


Faça um teste: conecte-se à VPN, retorne a essa tela, pesquise pelo seu login e marque o nível de severidade como DEBUG para ver todas as mensagens. Você deve encontrar entradas de log relacionadas ao seu usuário, o que é bem útil.

Date                Severity    Process         Line
2025-02-19T20:41:27-03:00 Notice openvpn_server4 ludarkstar99/177.177.177.177:51645 SIGUSR1[soft,ping-restart] received, client-instance restarting
2025-02-19T20:41:27-03:00 Notice openvpn_server4 ludarkstar99/177.177.177.177:51645 [ludarkstar99] Inactivity timeout (--ping-restart), restarting
2025-02-19T08:16:14-03:00 Notice openvpn_server4 ludarkstar99/177.177.177.177:51645 Protocol options: protocol-flags cc-exit tls-ekm dyn-tls-crypt

Agora, imagine que você quer apenas as linhas de autenticação bem-sucedida do usuário ludarkstar99. Filtrar apenas pelo login traz várias outras mensagens (inatividade, criptografia, certificado etc.). Se quiser apenas a linha que indica conexão bem-sucedida — algo como:

177.177.177.177:51645 [ludarkstar99] Peer Connection Initiated with [AF_INET6]::ffff:177.177.239.204:51645 (via 177.39.39.39%vmx0_vlan301)

Talvez você tente "[ludarkstar99] Peer Connection Initiated with" na caixa de pesquisa... e não encontre nada! Isso acontece porque o OPNsense remove caracteres especiais como `[]`, `+`, `&`, `$` etc.  e isso quebra a correspondência exata dos termos em sequência, pois falta os caracteres "[" e "]".

Então, como pesquisar tanto pelo nome do usuário quanto pelo texto que indica autenticação bem-sucedida? Em geral, sistemas de log permitem expressões regulares ou curingas. De fato, o OPNsense suporta algo do tipo, mas com ressalvas.



OS PRUDENTES VEEM O PERIGO E SE ABRIGAM

Sempre que surge um problema, gosto de pensar que esses desafios nos fazem crescer. Se eu simplesmente entregasse a solução de bandeja, você talvez não entendesse todo o processo. Então, vamos explorar como o OPNsense faz essa busca nos logs.

  • Abra as Ferramentas de Desenvolvedor do navegador (Ctrl+F12 ou Ctrl+Shift+I). 
  • No campo de pesquisa, digite, por exemplo: [ludarkstar99] Peer Connection Initiated
  • Observe a requisição na aba Rede: ela chama "/api/diagnostics/log/core/openvpn" com parâmetros searchPhrase e severity
A requisição chega ao servidor, que remove caracteres especiais e, em seguida, aciona o configd para executar a ação "system diag log", passando parâmetros como módulo (core), arquivo (openvpn) e severidades. Por fim, o configd chama o script /usr/local/opnsense/scripts/syslog/queryLog.py, que realiza a busca no arquivo de log. 

O ponto crucial é: esse script substitui o caractere "*" por ".*" (expressão regular) e, caso você não use "*", o script adiciona ".*" antes e depois do termo pesquisado. Isso significa que, na versão 24.1, se você quiser filtrar "ludarkstar99" + "Peer Connection Initiated" numa mesma linha, precisa usar o curinga "*". Por exemplo:

*ludarkstar99*Peer Connection Initiated

Dessa forma, o script consegue montar a expressão regular que "casa" com a linha completa, incluindo eventuais caracteres entre o usuário e o texto desejado.
Obs.: Repare que é é necessário antes do nome do usuário o caractere curinga (*) pois a linha de log não começa com o nome do usuário...



AS COISAS VELHAS JÁ PASSARAM, EIS QUE TUDO SE FEZ NOVO

Até aqui tudo bem para a versão 24.1. Mas e se você estiver na versão 24.7.3 em diante e nada funcionar? Pois é, houve mudanças!

Nessa versão, o script /usr/local/opnsense/scripts/syslog/queryLog.py foi alterado. Em vez de usar expressões regulares, a busca passou a ser literal, fazendo apenas "line.find(clause)". Ou seja, o conceito de "*" como coringa deixa de existir. Se você incluir vários termos, o sistema vai buscar todos eles na linha, mas não com curinga. 

Portanto, se quiser achar "ludarkstar99" e "Peer Connection Initiated" na mesma linha, basta digitar:

ludarkstar99 Peer Connection Initiated

Agora, o OPNsense procura cada palavra na linha. Se todas aparecerem, a linha é exibida. Se não, não aparece nada.



Conclusão: 
  • Na versão 24.7.2 (ou anteriores), use "*" como coringa para junções. 
  • Na versão 24.7.3 em diante, a busca se tornou literal e o "*" não tem mais efeito. Basta digitar todas as palavras que deseja encontrar na mesma linha. 

That's all folks.


Obs.: Esta mensagem foi melhorada com ajuda de I.A para trazer clareza e diminuir a densidade textual. o texto original possuía mais de 300 linhas, além de sarcasmo excessivo, piadas de mau gosto, e explicações profundamente duvidosas.
"O simples convence."
#10
Olá m4igor, seja bem vindo ao fórum.

Vamos deixar algo claro desde o início: Seu ambiente é um laboratório, e tem suas particularidades.

Nesse caso, você precisa que o gateway da rede 192.168.18.0/24 (ONT) direcione a rede 192.168.27.0/24 (via rota estática) para o IP do opnsense (wan) na rede 192.168.18.0/24 (próximo salto).
Assim o OPNsense vai receber as conexões pela wan destinadas a rede 27 e vai encaminhar via interface LAN para a rede interna dele. Lembra que a WAN do opnsense vem sem regra de liberação nenhuma, então vai ser necessário cria ao menos uma para autorizar a rede .18 chegar na rede .27.

O melhor a se fazer para você que está iniciando, e minimizar a complexidade, seria com que a ONT seja a WAN do opnsense, e que todos os seus outros aparelhos recebem a rede LAN do opnsense. assim todos os equipamentos internos estarão na rede 192.168.27.0/24 e você nem precisa se preocupar com rota.

- ahh mas eu quero segmentar a rede... então compra um appliance certinho, faz as vlans no switch e no firewall e seja feliz.
- ahh mas meu firewall tá virtualizado: segue a mesma lógica - faz as vlans no switch e no firewall sendo que o firewall que vai tá conectado no swich e não mais a ONT. a ONT só vai estar conectada na porta WAN do firewall.

INTERNET <--> ONT <--> PROXMOX/WAN-OPNSENSE <-->PROXMOX/LAN-OPNSENSE<-->SWITCH DA REDE/WIFI.
#11
Quote from: robi on December 16, 2024, 01:08:07 PMThanks for this script.
Question related to the "In all firewall rules or RDR (nat) must be a comment." requirement: comment means a the "Description" field in pfSense UI?
Why is this requirement imposed?

Hi Robi,
Yes, you need to set a description for each pfSense firewall/NAT rule.
This is a limitation I introduced to help identify already imported rules and avoid duplicates.

If an error occurs during the import process, you have the opportunity to correct it and re-import, skipping the rules that were already successfully imported.
#12
Hi jojothehumanmonkey,

[  ] Are you using certificates to authenticate users in this openvpn profile?
[  ] Did you checked the option "Username as CN"?
[  ] Does the term "Donald" matches the user certificate common name (case sensitive)?
[  ] In the field common name on screen Client Specific Overrides, have you verified any leading white space?

#13
it's not mandatory a "real" dns name for certificate common name for this purpose. in doubt use the internal dns name like fw01.doe.it.
but keep in mind: the name you insert there gonna be displayed in the connection status.
#14
Can you expand the log selection for what's surrounding the line:


2024-12-12T09:11:33 Error monit 'New_Firewall_Access_Detected' content match:

#15
Also, make sure there's a firewall rule in LAN interface, on top of the list, allowing the lan subnet (source) to the modem address (destination), without force any gateway or gateway group - just leave default.