
Galah: एक LLM-संचालित वेब हनीपॉट।
TL;DR: Galah (/ɡəˈlɑː/ - उच्चारण 'गुह-लाह') एक LLM-संचालित वेब हनीपॉट है जो विभिन्न अनुप्रयोगों की नकल करने और मनमाने HTTP अनुरोधों पर गतिशील रूप से प्रतिक्रिया देने के लिए डिज़ाइन किया गया है। Galah प्रमुख LLM प्रदाताओं का समर्थन करता है, जिनमें OpenAI, GoogleAI, GCP का Vertex AI, Anthropic, Cohere और Ollama शामिल हैं।
पारंपरिक वेब हनीपॉट्स के विपरीत, जो विशिष्ट वेब अनुप्रयोगों या कमजोरियों का मैन्युअल रूप से अनुकरण करते हैं, Galah किसी भी HTTP अनुरोध के लिए प्रासंगिक प्रतिक्रियाएँ—जिसमें HTTP हेडर और बॉडी सामग्री शामिल है—गतिशील रूप से तैयार करता है। LLM द्वारा उत्पन्न प्रतिक्रियाओं को समान अनुरोधों के लिए पुनरावृत्ति उत्पादन को रोकने के लिए एक कॉन्फ़िगरेबल अवधि के लिए कैश किया जाता है, जिससे API लागत कम होती है। कैशिंग पोर्ट-विशिष्ट होती है, यह सुनिश्चित करती है कि किसी विशेष पोर्ट के लिए उत्पन्न प्रतिक्रियाएँ उसी अनुरोध के लिए किसी भिन्न पोर्ट पर पुनः उपयोग नहीं की जाएँगी।
Galah वैकल्पिक रूप से आने वाले HTTP अनुरोधों को Suricata नियमों के एक सेट के विरुद्ध निरीक्षण कर सकता है, जो विभिन्न HTTP बफ़र्स पर मेल खाता है जिसमें मेथड, URI, हेडर, कुकीज़ और अनुरोध बॉडी शामिल है (वर्तमान कार्यान्वयन सभी Suricata कीवर्ड का समर्थन नहीं करता है, और PCRE हैंडलिंग सीमित है)। नियम मिलान को सक्षम और कॉन्फ़िगर करने के लिए, Suricata HTTP Rule Matching देखें।
प्रॉम्प्ट कॉन्फ़िगरेशन इस हनीपॉट में महत्वपूर्ण है। जबकि आप कॉन्फ़िगरेशन फ़ाइल में प्रॉम्प्ट को अपडेट कर सकते हैं, LLM को निर्दिष्ट JSON प्रारूप में प्रतिक्रिया उत्पन्न करने का निर्देश देने वाले खंड को बनाए रखना महत्वपूर्ण है।
नोट: Galah को LLM की HTTP संदेश तैयार करने की क्षमताओं का पता लगाने के लिए एक मजेदार सप्ताहांत परियोजना के रूप में विकसित किया गया था। हनीपॉट विभिन्न तरीकों जैसे कि नेटवर्क फ़िंगरप्रिंटिंग तकनीक, LLM प्रदाता और मॉडल के आधार पर लंबे समय तक प्रतिक्रिया समय, और गैर-मानक प्रतिक्रियाओं के माध्यम से पहचाना जा सकता है। डेनियल ऑफ वॉलेट हमलों से बचाने के लिए, अपने LLM API पर उपयोग सीमाएँ निर्धारित करना सुनिश्चित करें।
config.yaml फ़ाइल अपडेट करें।git clone [email protected]:0x4D31/galah.git
cd galah
go mod download
mkdir bin
go build -o bin/galah ./cmd/galah
./bin/galah --help
██████ █████ ██ █████ ██ ██
██ ██ ██ ██ ██ ██ ██ ██
██ ███ ███████ ██ ███████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██
██████ ██ ██ ███████ ██ ██ ██ ██
llm-based web honeypot | version 1.1.1
author: Adel "0x4D31" Ka
Usage: galah --provider PROVIDER --model MODEL [--server-url SERVER-URL] [--temperature TEMPERATURE] [--api-key API-KEY] [--cloud-location CLOUD-LOCATION] [--cloud-project CLOUD-PROJECT] [--interface INTERFACE] [--config-file CONFIG-FILE] [--rules-config-file RULES-CONFIG-FILE] [--event-log-file EVENT-LOG-FILE] [--cache-db-file CACHE-DB-FILE] [--cache-duration CACHE-DURATION] [--log-level LOG-LEVEL] [--suricata-enabled] [--suricata-rules-dir SURICATA-RULES-DIR]
Options:
--provider PROVIDER, -p PROVIDER
LLM प्रदाता (openai, googleai, gcp-vertex, anthropic, cohere, ollama) [env: LLM_PROVIDER]
--model MODEL, -m MODEL
LLM मॉडल (जैसे gpt-3.5-turbo-1106, gemini-1.5-pro-preview-0409) [env: LLM_MODEL]
--server-url SERVER-URL, -u SERVER-URL
LLM सर्वर URL (Ollama के लिए आवश्यक) [env: LLM_SERVER_URL]
--temperature TEMPERATURE, -t TEMPERATURE
LLM सैंपलिंग तापमान (0-2)। उच्च मान आउटपुट को अधिक यादृच्छिक बनाते हैं [default: 1, env: LLM_TEMPERATURE]
--api-key API-KEY, -k API-KEY
LLM API कुंजी [env: LLM_API_KEY]
--cloud-location CLOUD-LOCATION
LLM क्लाउड स्थान क्षेत्र (GCP के Vertex AI के लिए आवश्यक) [env: LLM_CLOUD_LOCATION]
--cloud-project CLOUD-PROJECT
LLM क्लाउड प्रोजेक्ट ID (GCP के Vertex AI के लिए आवश्यक) [env: LLM_CLOUD_PROJECT]
--interface INTERFACE, -i INTERFACE
सर्व करने के लिए इंटरफ़ेस
--config-file CONFIG-FILE, -c CONFIG-FILE
कॉन्फ़िग फ़ाइल का पथ [default: config/config.yaml]
--rules-config-file RULES-CONFIG-FILE, -r RULES-CONFIG-FILE
नियम कॉन्फ़िग फ़ाइल का पथ (यदि छोड़ा गया तो नियम इंजन अक्षम हो जाता है)
--event-log-file EVENT-LOG-FILE, -o EVENT-LOG-FILE
घटना लॉग फ़ाइल का पथ [default: event_log.json]
--cache-db-file CACHE-DB-FILE, -f CACHE-DB-FILE
प्रतिक्रिया कैशिंग के लिए डेटाबेस फ़ाइल का पथ [default: cache.db]
--cache-duration CACHE-DURATION, -d CACHE-DURATION
उत्पन्न प्रतिक्रियाओं के लिए कैश अवधि (घंटों में)। कैशिंग अक्षम करने के लिए 0 का उपयोग करें, और असीमित कैशिंग (कोई समाप्ति नहीं) के लिए -1 का उपयोग करें। [default: 24]
--log-level LOG-LEVEL, -l LOG-LEVEL
लॉग स्तर (debug, info, error, fatal) [default: info]
--suricata-enabled Suricata HTTP नियम जाँच सक्षम करें (default: false)
--suricata-rules-dir SURICATA-RULES-DIR
HTTP अनुरोधों की जाँच करने के लिए Suricata .rules फ़ाइलों वाली निर्देशिका
--help, -h यह सहायता प्रदर्शित करें और बाहर निकलें
% git clone [email protected]:0x4D31/galah.git
% cd galah
% mkdir logs
% export LLM_API_KEY=your-api-key
% docker build -t galah-image .
% docker run -d --name galah-container -p 8080:8080 -v $(pwd)/logs:/galah/logs -e LLM_API_KEY galah-image -o logs/galah.json -p openai -m gpt-3.5-turbo-1106
./galah -p openai -m gpt-4.1-mini --suricata-enabled --suricata-rules-dir rules
परीक्षण:
curl --http1.1 --path-as-is -X POST \
-H 'SOAPAction: "http://purenetworks.com/HNAP1/GetGuestNetworkSettings"' \
-H 'Content-Type: text/xml' \
--data '<GetGuestNetworkSettings xmlns="http://purenetworks.com/HNAP1/">' \
http://127.0.0.1:8888/HNAP1/ -v
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 127.0.0.1:8888...
* Connected to 127.0.0.1 (127.0.0.1) port 8888
> POST /HNAP1/ HTTP/1.1
> Host: 127.0.0.1:8888
> User-Agent: curl/8.7.1
> Accept: */*
> SOAPAction: "http://purenetworks.com/HNAP1/GetGuestNetworkSettings"
> Content-Type: text/xml
> Content-Length: 64
>
* upload completely sent off: 64 bytes
< HTTP/1.1 200 OK
< Server: TP-LINK HTTP Server/1.0
< Date: Mon, 21 Apr 2025 01:28:43 GMT
< Content-Length: 545
< Content-Type: text/xml; charset=utf-8
<
<?xml version="1.0" encoding="utf-8"?>
<GetGuestNetworkSettingsResponse xmlns="http://purenetworks.com/HNAP1/">
<GetGuestNetworkSettingsResult>OK</GetGuestNetworkSettingsResult>
<GuestNetworkEnabled>true</GuestNetworkEnabled>
<GuestNetworkSSID>TPLink_Guest</GuestNetworkSSID>
<GuestNetworkSecurity>WPA2-PSK</GuestNetworkSecurity>
<GuestNetworkPassword>guest1234</GuestNetworkPassword>
<GuestNetworkIsolation>true</GuestNetworkIsolation>
<GuestNetworkSSIDBroadcast>true</GuestNetworkSSIDBroadcast>
JSON ईवेंट लॉग:
{
"eventTime": "2025-04-21T02:28:43.583386+01:00",
"httpRequest": {
"body": "<GetGuestNetworkSettings xmlns=\"http://purenetworks.com/HNAP1/\">",
"bodySha256": "836c42168ebbad0b7192daa70ad8e4ea8d5930097162f513045f5ecb6ae9d5bd",
"headers": {
"Accept": "*/*",
"Content-Length": "64",
"Content-Type": "text/xml",
"Soapaction": "\"http://purenetworks.com/HNAP1/GetGuestNetworkSettings\"",
"User-Agent": "curl/8.7.1"
},
"headersSorted": "Accept,Content-Length,Content-Type,Soapaction,User-Agent",
"headersSortedSha256": "3a44fecf9284eca3947c45ffeb2301ce6d9b3d0a3cc5a7491ccea2b6ed61edaa",
"method": "POST",
"protocolVersion": "HTTP/1.1",
"request": "/HNAP1/",
"sessionID": "1745198923587092000_qHLNEPBNPrH6qw==",
"userAgent": "curl/8.7.1"
},
"httpResponse": {
"headers": {
"Content-Length": "454",
"Content-Type": "text/xml; charset=utf-8",
"Server": "TP-LINK HTTP Server/1.0"
},
"body": "<?xml version=\"1.0\" encoding=\"utf-8\"?> <GetGuestNetworkSettingsResponse xmlns=\"http://purenetworks.com/HNAP1/\"> <GetGuestNetworkSettingsResult>OK</GetGuestNetworkSettingsResult> <GuestNetworkEnabled>true</GuestNetworkEnabled> <GuestNetworkSSID>TPLink_Guest</GuestNetworkSSID> <GuestNetworkSecurity>WPA2-PSK</GuestNetworkSecurity> <GuestNetworkPassword>guest1234</GuestNetworkPassword> <GuestNetworkIsolation>true</GuestNetworkIsolation> <GuestNetworkSSIDBroadcast>true</GuestNetworkSSIDBroadcast> </GetGuestNetworkSettingsResponse>"
},
"level": "info",
"msg": "successfulResponse",
"port": "8888",
"responseMetadata": {
"generationSource": "llm",
"info": {
"model": "gpt-4.1-mini",
"provider": "openai",
"temperature": 1
}
},
"sensorName": "mbp",
"srcHost": "localhost",
"srcIP": "127.0.0.1",
"srcPort": "62418",
"suricataMatches": [
{
"msg": "ET WEB_SPECIFIC_APPS D-Link DIR-823G Multiple HNAP SOAPAction Endpoints Authentication Bypass",
"sid": "2061623"
}
],
"tags": null,
"time": "2025-04-21T02:28:43.587152+01:00"
}
अधिक उदाहरण यहाँ देखें।
galah पैकेज को एक स्टैंडअलोन लाइब्रेरी के रूप में उपयोग किया जा सकता है। एक galah.Service बनाएँ और प्रतिक्रिया उत्पन्न करने के लिए http.Request के साथ GenerateHTTPResponse को कॉल करें। यदि ConfigFile, EventLogFile, या CacheDBFile छोड़ दिए जाते हैं, तो उनके डिफ़ॉल्ट पथ (config/config.yaml, event_log.json, और cache.db) का उपयोग किया जाता है। नियम जाँच को सक्षम करने के लिए RulesConfigFile निर्दिष्ट करें; इसे खाली छोड़ने से नियम इंजन पूरी तरह से अक्षम हो जाता है। Options.Logger को *log.Logger के साथ प्रदान किया जा सकता है; यदि nil है, तो Galah एक डिफ़ॉल्ट टेक्स्ट लॉगर बनाता है।
svc, err := galah.NewService(context.Background(), galah.Options{
LLMProvider: "openai",
LLMModel: "gpt-4.1-mini",
LLMAPIKey: "YOUR_KEY",
ConfigFile: "config/config.yaml",
RulesConfigFile: "config/rules.yaml", // नियम इंजन अक्षम करने के लिए छोड़ें
EventLogFile: "event_log.json",
CacheDBFile: "cache.db",
Logger: log.NewWithOptions(os.Stderr, log.Options{}),
})
if err != nil {
log.Fatal(err)
}
req, _ := http.NewRequest("GET", "https://example.com", nil)
respBytes, err := svc.GenerateHTTPResponse(req, "8080")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(respBytes))
आप पहले से लोड किए गए कॉन्फ़िगरेशन से भी एक सेवा बना सकते हैं:
cfg, _ := config.LoadConfig("config.yaml")
rulesCfg, _ := config.LoadRules("rules.yaml")
svc, err := galah.NewServiceFromConfig(context.Background(), cfg, rulesCfg.Rules, galah.Options{
LLMProvider: "openai",
LLMModel: "gpt-4.1-mini",
LLMAPIKey: "YOUR_KEY",
EventLogFile: "event_log.json", // खाली होने पर डिफ़ॉल्ट का उपयोग करें
CacheDBFile: "cache.db", // खाली होने पर डिफ़ॉल्ट का उपयोग करें
Logger: log.NewWithOptions(os.Stderr, log.Options{}),
})
नियम जाँच को पूरी तरह से बंद करने के लिए, सेवा बनाते समय RulesConfigFile छोड़ें या NewServiceFromConfig को nil/खाली स्लाइस पास करें। किसी भी अप्रयुक्त विकल्प फ़ील्ड को उनके डिफ़ॉल्ट पर निर्भर रहने के लिए खाली छोड़ा जा सकता है।
सेवा लाइब्रेरी के रूप में उपयोग करने पर कैश और ईवेंट लॉगिंग के लिए हेल्पर विधियाँ भी प्रदान करती है:
respBytes, _ := svc.CheckCache(req, "8080") // यदि कोई कैशेड प्रविष्टि नहीं है तो nil लौटाता है
svc.LogEvent(req, llm.JSONResponse{Headers: map[string]string{"Content-Type": "text/plain"}, Body: "hi"}, "8080", "llm", nil)