_Créditos das imagens: Copilot_
## Solução com HAProxy para Redirecionamento "Inteligente?": Caso de Sucesso e Desafios
Na era da conectividade global, pequenas empresas enfrentam desafios únicos ao fornecer acesso remoto seguro para suas aplicações internas. Este artigo descreve como uma consultoria solucionou o problema de redirecionamento de tráfego para servidores TOTVS Application Server usando **HAProxy** e Lua. Também abordamos possíveis melhorias e limitações dessa abordagem.
---
### **Cenário e Desafios**
1. **IP Dinâmico no Servidor Central**
O servidor da consultoria utiliza um endereço dinâmico acessível via serviços como **No-IP** ou **DuckDNS**.
2. **Desenvolvedores com IPs Dinâmicos**
Os desenvolvedores acessam o servidor de locais variados, dificultando a configuração estática de firewalls ou ACLs.
3. **Porta Única para Acesso (1234)**
Por motivos de segurança, apenas a porta 1234 está aberta para comunicação com os servidores internos.
---
### **Solução Implementada**
Para gerenciar essas complexidades, a consultoria configurou um **HAProxy para Windows** compilado com suporte a Lua (disponível no [repositório do GitHub](https://github.com/naldodj/naldodj-haproxy-windows)). Com ele, foi possível:
1. **Verificar Origem do IP**
ACLs foram usadas para identificar ranges de IPs e redirecionar as conexões de maneira inteligente.
2. **Log Detalhado das Conexões**
Um servidor hb_syslog ([disponível aqui](https://github.com/naldodj/naldodj-hb_syslog)) registrou as conexões para auditoria.
3. **Redirecionamento por ACLs e Payloads**
Dependendo da origem e do conteúdo inicial da conexão, os desenvolvedores eram direcionados para o backend correto.
---
### **Configuração do HAProxy**
A configuração envolveu:
#### **Trecho Principal**
```haproxy
frontend tcp_frontend_protheus
mode tcp
bind *:1234
# Chamada ao script Lua
tcp-request content lua.log_transaction_tcp
# ACLs para identificar IPs e redirecionar
acl is_range1 src 191.199.192.0/18
acl is_range2 src 170.244.192.0/18
use_backend tcp_backend_protheus_1235 if is_range1
use_backend tcp_backend_protheus_1236 if is_range2
# Default para IPs desconhecidos
default_backend tcp_backend_protheus_1236
```
#### **Script em Lua**
O script gerou logs detalhados para conexões TCP:
```lua
-- Records the "log_transaction" action to capture detailed transaction information.
local function safe_execute(func, description)
local success, result = pcall(func)
if not success then
core.Alert("safe_execute :: Error while processing: " .. description .. " - " .. result)
return nil
end
return result
end
-- Log para transações HTTP
core.register_action("log_transaction_http", { "http-req" }, function(txn)
core.Info("=== log_transaction_http :: New HTTP connection ===")
-- Informações gerais
core.Info("log_transaction_http :: Source: " .. safe_execute(function() return txn.f:src() .. ":" .. txn.f:src_port() end, "Source Info") or "Unavailable")
core.Info("log_transaction_http :: Destination: " .. safe_execute(function() return txn.f:dst() .. ":" .. txn.f:dst_port() end, "Destination Info") or "Unavailable")
-- Identificação do frontend e backend
core.Info("log_transaction_http :: Frontend: " .. (safe_execute(function() return txn.f:fe_name() end, "Frontend Name") or "Unidentified"))
core.Info("log_transaction_http :: Backend: " .. (safe_execute(function() return txn.f:be_name() end, "Backend Name") or "Unidentified"))
-- Informações HTTP específicas
core.Info("log_transaction_http :: HTTP Method: " .. (safe_execute(function() return txn.f:method() end, "HTTP Method") or "Unavailable"))
core.Info("log_transaction_http :: HTTP Path: " .. (safe_execute(function() return txn.f:path() end, "HTTP Path") or "Unavailable"))
-- Cabeçalhos HTTP
local headers = safe_execute(function() return txn.http:req_get_headers() end, "HTTP Headers")
if headers and type(headers) == "table" then
core.Info("log_transaction_http :: HTTP Headers Request:")
for hdr, value in pairs(headers) do
if type(value) == "table" then
core.Info("log_transaction_http :: " .. hdr .. ": " .. table.concat(value, ", "))
else
core.Info("log_transaction_http :: " .. hdr .. ": " .. tostring(value))
end
end
else
core.Info("log_transaction_http :: HTTP Headers Request: Unavailable")
end
-- Informações sobre tempos
core.Info("log_transaction_http :: Time since acceptance on the frontend: " .. (safe_execute(function() return txn.f:time_frontend_accept() end, "Frontend Accept Time") or "Unavailable") .. " ms")
core.Info("log_transaction_http :: Time to connect to the backend: " .. (safe_execute(function() return txn.f:time_backend_connect() end, "Backend Connect Time") or "Unavailable") .. " ms")
core.Info("=== log_transaction_http :: End of HTTP Connection ===")
end)
-- Log para transações TCP
core.register_action("log_transaction_tcp", { "tcp-req" }, function(txn)
core.Info("=== log_transaction_tcp :: New TCP connection ===")
-- Informações da origem
core.Info("log_transaction_tcp :: Source IP: " .. (safe_execute(function() return txn.f:src() end, "Source IP") or "Unavailable"))
core.Info("log_transaction_tcp :: Port of Origin: " .. (safe_execute(function() return txn.f:src_port() end, "Source Port") or "Unavailable"))
-- Informações do destino
core.Info("log_transaction_tcp :: Destination IP: " .. (safe_execute(function() return txn.f:dst() end, "Destination IP") or "Unavailable"))
core.Info("log_transaction_tcp :: Destination Port: " .. (safe_execute(function() return txn.f:dst_port() end, "Destination Port") or "Unavailable"))
-- Identificação do Frontend e Backend
core.Info("log_transaction_tcp :: Frontend: " .. (safe_execute(function() return txn.f:fe_name() end, "Frontend Name") or "Unidentified"))
core.Info("log_transaction_tcp :: Backend: " .. (safe_execute(function() return txn.f:be_name() end, "Backend Name") or "Unidentified"))
-- Estados da conexão
core.Info("log_transaction_tcp :: Connection Status: " .. (safe_execute(function() return txn.f:state() end, "Connection State") or "Unidentified"))
-- Informações sobre tempo
core.Info("log_transaction_tcp :: Time since acceptance on the frontend: " .. (safe_execute(function() return txn.f:time_frontend_accept() end, "Frontend Accept Time") or "Unavailable") .. " ms")
core.Info("log_transaction_tcp :: Time to connect to the backend: " .. (safe_execute(function() return txn.f:time_backend_connect() end, "Backend Connect Time") or "Unavailable") .. " ms")
core.Info("log_transaction_tcp :: Backend response time: " .. (safe_execute(function() return txn.f:time_backend_response() end, "Backend Response Time") or "Unavailable") .. " ms")
-- Tamanho da requisição e resposta
core.Info("log_transaction_tcp :: Requisition Size: " .. (safe_execute(function() return txn.f:req_len() end, "Request Size") or "Unavailable") .. " bytes")
core.Info("log_transaction_tcp :: Response Size: " .. (safe_execute(function() return txn.f:res_len() end, "Response Size") or "Unavailable") .. " bytes")
-- Logs de erro
core.Info("log_transaction_tcp :: Error Code: " .. (safe_execute(function() return txn.f:err_code() end, "Error Code") or "None"))
core.Info("log_transaction_tcp :: Error State: " .. (safe_execute(function() return txn.f:err_state() end, "Error State") or "None"))
core.Info("=== log_transaction_tcp :: End of TCP Connection ===")
end)
```
---
#### Exemplo de Registro no Syslog:
```plaintext
2024-12-06 11:31:37 -- hb_syslog start --
2024-12-06 11:31:38 INFO: <134>/ Dec 6 11:31:38 haproxy[506]: Connect from ::1:49307 to ::1:8404 (stats/HTTP)
2024-12-06 11:31:39 INFO: <134>/ Dec 6 11:31:39 haproxy[506]: === log_transaction_tcp :: New TCP connection ===
2024-12-06 11:31:39 INFO: <134>/ Dec 6 11:31:39 haproxy[506]: log_transaction_tcp :: Source IP: 191.199.206.183
2024-12-06 11:31:39 INFO: <134>/ Dec 6 11:31:39 haproxy[506]: log_transaction_tcp :: Port of Origin: 55230
2024-12-06 11:31:39 INFO: <134>/ Dec 6 11:31:39 haproxy[506]: log_transaction_tcp :: Destination IP: 192.168.15.3
2024-12-06 11:31:39 INFO: <134>/ Dec 6 11:31:39 haproxy[506]: log_transaction_tcp :: Destination Port: 1234
```
---
## Benefícios e Problemas Potenciais
### Benefícios:
1. **Redirecionamento Dinâmico**: O sistema atende a diferentes ranges de IP ou IPs específicos, assegurando o acesso ao backend correto.
2. **Centralização de Logs**: Logs detalhados permitem auditoria e solução de problemas.
3. **Custo Zero**: Tanto o HAProxy quanto os scripts personalizados são gratuitos.
### Problemas Potenciais:
1. **Manutenção de Scripts**: Alterações nos ranges de IP ou regras exigem atualizações frequentes na configuração.
2. **Overhead de Processamento**: A execução de scripts Lua em conexões de alta frequência pode impactar o desempenho.
3. **Dependência de IPs Públicos**: O uso de IPs dinâmicos pode causar falhas temporárias, mesmo com serviços como No-IP ou DuckDNS.
---
### **Resultados**
- **Melhoria no Controle de Acesso**
Os desenvolvedores acessavam os servidores corretos sem intervenção manual.
- **Auditoria Simplificada**
Os logs detalhados registraram tentativas de acesso, ajudando na identificação de comportamentos anômalos.
---
### **Limitações e Possíveis Melhorias**
1. **Dependência de IP Dinâmico**
Embora serviços como **No-IP** resolvam parte do problema, IPs dinâmicos ainda podem introduzir atrasos devido à atualização do DNS.
2. **Configuração Complexa**
Manter ACLs atualizadas manualmente pode se tornar trabalhoso, especialmente com equipes remotas em expansão.
3. **Segurança Adicional**
Implementar autenticação baseada em certificados ou VPN poderia elevar a segurança significativamente.
---
## Soluções Alternativas
Se sua empresa busca uma solução ainda mais simples e gratuita, aqui estão algumas sugestões:
1. **VPN Dinâmica com WireGuard**: Configurar um túnel seguro com WireGuard oferece acesso seguro sem depender de regras IP no proxy.
2. **NGINX com Resolução Dinâmica**: Utilizar NGINX com upstreams dinâmicos para redirecionar conexões com base em domínios em vez de IPs.
3. **Proxy Reverso com ZeroTier**: Criar uma rede virtual que elimina a necessidade de lidar diretamente com IPs dinâmicos.
Recomendamos o uso do **WireGuard**, uma VPN leve e gratuita que pode integrar desenvolvedores em um túnel seguro. Com o WireGuard:
- O redirecionamento de tráfego torna-se transparente.
- A comunicação é criptografada ponta a ponta.
- A configuração e o gerenciamento de IPs dinâmicos são minimizados.
---
### **Conclusão**
A solução com HAProxy atendeu às necessidades imediatas da consultoria, oferecendo redirecionamento inteligente e log detalhado. No entanto, a adoção de soluções como **WireGuard** pode simplificar e fortalecer ainda mais o acesso remoto. Ferramentas gratuitas e de código aberto continuam sendo aliadas poderosas para pequenas empresas.
---
### **Links Importantes**
- [HAProxy para Windows com Lua](https://github.com/naldodj/naldodj-haproxy-windows)
- [Syslog em Harbour](https://github.com/naldodj/naldodj-hb_syslog)
---
### **Hashtags**
#HAProxy #LuaProgramming #SegurançaDigital #TOTVS #ConsultoriaTecnológica #IPDinâmico #LogsTCP #Redirecionamento #WireGuard #DevOps
---
134>134>134>134>134>134>
Comentários
Postar um comentário