Pular para o conteúdo principal

Postagem em destaque

BlackTDN :: LeetCode :: Comparando Implementações Harbour e TLPP para o Desafio Longest Palindromic Substring

_Créditos das imagens: ChatGPT_ ### LeetCode :: Comparando Implementações Harbour e TLPP para o Desafio Longest Palindromic Substring Resolver o problema do [Longest Palindromic Substring](https://leetcode.com/problems/longest-palindromic-substring/description/) é um exercício clássico de programação, que desafia desenvolvedores a encontrar a maior substring palindrômica dentro de uma string. Recentemente, exploramos soluções tanto em Harbour quanto em TLPP (Total Language Protheus Programming). Neste artigo, comparamos as implementações nessas duas linguagens, destacando suas semelhanças, diferenças e funcionalidades específicas. #### Implementações em Harbour ##### Versão 5.1 Essa solução utiliza a técnica de expansão a partir do centro do palíndromo. Cada caractere ou par de caracteres consecutivos é considerado um possível "centro". O algoritmo expande em ambas as direções enquanto os caracteres forem iguais, retornando o maior palíndromo encontrado. ##### Versão 5....

BlackTDN :: Solução com HAProxy para Redirecionamento "Inteligente?": Caso de Sucesso e Desafios



_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

---


Comentários

Postagens mais visitadas