yatuk/tamga
GitHub: yatuk/tamga
一款自托管的企业级 LLM API 安全代理,在应用与大模型供应商之间实时执行 PII 脱敏、密钥拦截与提示注入防御,助力数据合规。
Stars: 32 | Forks: 1
Tamga
Enterprise LLM API Security, Policy-Based Guard for Every Prompt
Goproxy |
Pythonanalyzer |
Next.jsdashboard |
| Reverse Proxy + Scanners |
Deep Analysis + Reports |
Management + Visibility |
## What is Tamga?  **Tamga** sits between your application and LLM providers (OpenAI, Anthropic, Azure, Vertex), scanning every prompt and response in real time and enforcing your security policy before data leaves your network. | Your challenge | Tamga's answer | |:---|---| | PII leaking through prompts | Detect + **REDACT** credit cards, TC Kimlik, IBAN, email, phone before they reach the provider | | API keys pasted into chat | **BLOCK** secrets (AWS, GitHub, OpenAI keys, JWT, connection strings) inline | | Prompt injection attacks | Pattern-based injection detection with configurable sensitivity | | Zero visibility into AI usage | Event bus + optional PostgreSQL logging + REST API for stats | | Scattered policies per app | Single YAML policy file: hot-reload, API-managed, version-controlled | ## Architecture  View the [D2 source](docs/architecture/tamga.d2) or [full-size PNG](docs/architecture/tamga.png).
Component details
| Component | Language | Role | Port | |---|---|---|---| | **Proxy** | Go | Inline scanners, policy engine, reverse proxy, rate limiter, REST API | `8443` | | **Analyzer** | Python | Deep PII/injection/toxicity analysis, compliance reports | `8444` | | **Dashboard** | Next.js | Admin UI, incident hunting, integrations, OWASP coverage | `3000` | | **PostgreSQL** | — | Optional persistent telemetry & audit storage | `5432` | | **Redis** | — | Rate limiting, caching, distributed counters | `6379` | | **Jaeger** | — | OpenTelemetry tracing (optional) | `16686` |:8443 TLS
:8080 metrics] end subgraph "Inspection" Analyzer[Analyzer
:50051 gRPC
:8444 HTTP] end subgraph "Data" Postgres[(PostgreSQL 16
:5432)] Redis[(Redis 7
:6379)] end subgraph "Observability" Jaeger[Jaeger
:16686 UI
:4317 OTLP] end subgraph "Management" Dashboard[Dashboard
:3000 Next.js] end end Client -->|HTTPS| Proxy Proxy -->|gRPC| Analyzer Proxy -->|SQL| Postgres Proxy -->|cache + rate limit| Redis Proxy -->|OTLP traces| Jaeger Dashboard -->|REST API| Proxy Dashboard -->|read events| Postgres classDef edge fill:#1e3a5f,stroke:#3b82f6,color:#dbeafe classDef inspection fill:#0d3a3a,stroke:#14b8a6,color:#ccfbf1 classDef data fill:#2d1b4e,stroke:#a855f7,color:#e9d5ff class Proxy edge class Analyzer inspection class Postgres,Redis data ┌──────────────────────────────────────────────────────────┐ │ Tamga Stack (docker-compose) │ │ │ │ ┌────────────┐ ┌──────────────┐ ┌─────────────┐ │ │ │ Proxy │───▶│ Analyzer │ │ Dashboard │ │ │ │ :8443 │ │ :50051 gRPC │ │ :3000 │ │ │ └─────┬──────┘ └──────────────┘ └──────┬──────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌──────────┐ ┌─────────┐ ┌──────────────────────┐ │ │ │ Postgres │ │ Redis │ │ Jaeger (OTEL) │ │ │ │ :5432 │ │ :6379 │ │ :16686 UI │ │ │ └──────────┘ └─────────┘ └──────────────────────┘ │ └──────────────────────────────────────────────────────────┘ ▲ │ HTTPS :8443 ┌────┴────┐ │ Client │ └─────────┘ View the [full-size deployment diagram](docs/architecture/deployment.svg) or [D2 source](docs/architecture/deployment.d2). ## How it works ### Request lifecycle What happens when your app sends an LLM request through Tamga: %%{init: { 'theme': 'dark', 'themeVariables': { 'primaryColor': '#1e3a5f', 'primaryTextColor': '#dbeafe', 'primaryBorderColor': '#3b82f6', 'lineColor': '#6b7280', 'background': '#0f172a', 'mainBkg': '#1e293b' } }}%% sequenceDiagram autonumber participant App as Your App participant Proxy as Tamga Proxy participant Scanner as Scanner Pipeline participant Policy as Policy Engine participant Analyzer as Analyzer (Python) participant LLM as LLM Provider participant DB as PostgreSQL App->>Proxy: POST /v1/messages Note over Proxy: Authenticate API key
Check rate limit (Redis) Proxy->>Scanner: Inline scan (input) Note over Scanner: 7 scanners run
(~3-5ms) Scanner-->>Proxy: Findings + confidence alt Confidence 0.3-0.9 (uncertain) Proxy->>Analyzer: gRPC deep scan Note over Analyzer: Presidio NER
+ LLM-as-judge Analyzer-->>Proxy: Enriched findings end Proxy->>Policy: Evaluate findings alt action = block Policy-->>Proxy: BLOCK Proxy-->>App: 403 Forbidden + reasons Proxy->>DB: Log incident (async) else action = redact Policy-->>Proxy: REDACT Note over Proxy: Mask findings in payload Proxy->>LLM: Forward redacted request LLM-->>Proxy: Response Proxy->>Scanner: Output scan Proxy-->>App: 200 OK + scan headers else action = pass Policy-->>Proxy: PASS Proxy->>LLM: Forward original LLM-->>Proxy: Response Proxy->>Scanner: Output scan Proxy-->>App: 200 OK end Proxy->>DB: Persist request_log (batched) Typical latency: 3-8ms scan + provider latency (usually 500-3000ms). Tamga overhead is less than 2% of total request time. View the [D2 source](docs/architecture/request-lifecycle.d2) or [full-size SVG](docs/architecture/request-lifecycle.svg). ## Benchmarks All benchmarks are reproducible from a single command (`go run ./cmd/redteam`) against a public 309-prompt adversarial corpus. No cherry-picking. | Metric | Value | Notes | |--------|-------|-------| | **Precision** | **96.9%** | Of mitigated prompts, 96.9% were genuinely adversarial — governs false-positive rate | | **Recall** | **48.4%** | Deterministic DFA catches ~48% on its own; remainder needs semantic reasoning (Shadow ML) | | **F1 Score** | **0.646** | Harmonic mean of precision and recall | | **Scan Latency p95** | **0.52 ms** | Single request, commodity hardware (Go 1.22, Windows amd64) | | **Scan Latency p99** | **0.58 ms** | Worst-case deterministic hot path | | **Scan Latency max** | **0.77 ms** | Well under 5ms budget | | **Total Overhead** | **< 2 ms** | Sub-millisecond static scanning via Aho-Corasick DFA; measured ~1.2ms on consumer hardware | | **Corpus** | **309 prompts** | ~40% benign, 60% adversarial/PII/secret — CI-gated, not a marketing dataset | → [Full benchmark report](docs/benchmarks/README.md) · [Red team dataset](proxy/testdata/redteam/prompts.csv) · [Go performance benchmarks](docs/benchmarks/README.md#go-performance-benchmarks-v011) ### Load Performance k6 benchmarks on a single-process Go proxy, 4-core consumer CPU, 16 GB RAM, NVMe SSD. No GPU, no SIMD tuning. Full scripts at `tests/stress/k6/`. | Workload | RPS | P50 | P95 | P99 | Errors | |----------|-----|-----|-----|-----|--------| | Clean prompts | 100 | 3.7ms | 5.5ms | 7.1ms | 0% | | Clean prompts | 500 | 1.6ms | 3.7ms | 8.9ms | 0% | | Clean prompts | 1000 | 6.2ms | 130ms | 167ms | 0% | | Mixed (70% clean, 20% PII, 10% adversarial) | 300 | 1.5ms | 2.7ms | 4.4ms | 0% | | Connection saturation | 5000 VUs | — | — | — | 88% TCP reject (expected) | ### Scanner pipeline 7 inline scanners run on every request. Hybrid design: fast scanners run sequentially to avoid goroutine overhead, while slower scanners run in parallel to hide their 1-2ms latency. %%{init: { 'theme': 'dark', 'themeVariables': { 'primaryColor': '#1e3a5f', 'primaryTextColor': '#dbeafe', 'primaryBorderColor': '#3b82f6', 'lineColor': '#6b7280', 'background': '#0f172a', 'mainBkg': '#1e293b' } }}%% graph LR Input[Request Content] --> Normalize[Unicode
Normalization] Normalize --> Fast{Fast
Scanners} Normalize --> Slow{Slow
Scanners} Fast -.->|0.3ms| PII[PII
email, TC, IBAN] Fast -.->|0.3ms| Secret[Secrets
API keys, tokens] Fast -.->|0.2ms| Comp[Competitor
brand names] Fast -.->|0.2ms| Custom[Custom Entity
policy-driven] Slow -.->|1.5ms| Inject[Injection
DFA + LLM judge] Slow -.->|1.2ms| Mod[Moderation
toxicity, hate] Slow -.->|0.6ms| Jail[Jailbreak
DAN, STAN] PII --> Merge[Findings
Aggregator] Secret --> Merge Comp --> Merge Custom --> Merge Inject --> Merge Mod --> Merge Jail --> Merge Merge --> Confidence{Confidence
Score} Confidence -->|< 0.3| Skip[Skip deep scan] Confidence -->|0.3-0.9| Deep[Analyzer gRPC] Confidence -->|> 0.9| Decisive[Use inline result] classDef fast fill:#1e3a5f,stroke:#3b82f6,color:#dbeafe classDef slow fill:#3a1f5f,stroke:#a855f7,color:#e9d5ff class PII,Secret,Comp,Custom fast class Inject,Mod,Jail slow Request Content │ ▼ ┌─────────────┐ │ Normalize │ ← NFKC + homoglyph + zero-width strip │ (Unicode) │ └──────┬──────┘ │ ┌───┴───┐ │ │ ▼ ▼ ┌─────┐ ┌─────┐ │Fast │ │Slow │ └──┬──┘ └──┬──┘ │ │ │ Fast (sequential, <0.5ms each): │ • PII (email, TC, IBAN) │ • Secrets (API keys, tokens) │ • Competitor (brand names) │ • Custom (policy-driven) │ │ Slow (parallel, 0.6-1.5ms each): │ • Injection (DFA + LLM judge) │ • Moderation (toxicity, hate) │ • Jailbreak (DAN, STAN) │ └───┬────┘ │ ▼ ┌─────────────┐ │ Aggregate │ │ Findings │ └──────┬──────┘ │ ▼ Confidence ────────── < 0.3 → Skip deep scan 0.3 - 0.9 → Analyzer gRPC > 0.9 → Use inline (block/redact) ### Policy decisions How Tamga determines whether to block, redact, warn, or pass a request. Decision order matters: the earliest deny wins. %%{init: { 'theme': 'dark', 'themeVariables': { 'primaryColor': '#1e3a5f', 'primaryTextColor': '#dbeafe', 'primaryBorderColor': '#3b82f6', 'lineColor': '#6b7280', 'background': '#0f172a', 'mainBkg': '#1e293b' } }}%% flowchart TD Start([Request received]) --> HasFindings{Any findings?} HasFindings -->|No| Pass([PASS
Forward to LLM]) HasFindings -->|Yes| CheckProvider{Provider
allowed?} CheckProvider -->|No| Block403([BLOCK 403
Provider not allowed]) CheckProvider -->|Yes| EvalRules{Match policy
rules?} EvalRules -->|No rule matched| DefaultAction([Apply default action
usually PASS]) EvalRules -->|Rule matched| RuleAction{Rule action?} RuleAction -->|block| Block403b([BLOCK 403
Policy violation]) RuleAction -->|redact| Mask[Mask findings in payload
e.g. 4532•••0366] RuleAction -->|warn| Webhook[Fire webhook
continue request] RuleAction -->|pass| PassRule([PASS]) Mask --> CheckBudget{Daily budget
OK?} Webhook --> CheckBudget PassRule --> CheckBudget CheckBudget -->|Exceeded| Block429([BLOCK 429
Budget exceeded]) CheckBudget -->|OK| CheckRate{Rate limit
OK?} CheckRate -->|Exceeded| Block429b([BLOCK 429
Rate limited]) CheckRate -->|OK| Forward([Forward to LLM]) classDef pass fill:#0d3a3a,stroke:#14b8a6,color:#ccfbf1 classDef block fill:#3a0d0d,stroke:#ef4444,color:#fecaca classDef warn fill:#3a2d0a,stroke:#f59e0b,color:#fef3c7 class Pass,PassRule,Forward pass class Block403,Block403b,Block429,Block429b block class Mask,Webhook warn ┌────────────────────────────────────────────────────────────────┐ │ Decision Order (first match wins) │ ├────┬──────────────────────────┬─────────────────┬──────────────┤ │ # │ Check │ If fails │ Action │ ├────┼──────────────────────────┼─────────────────┼──────────────┤ │ 1 │ Provider allowed? │ Not in allowlist│ BLOCK 403 │ │ 2 │ Policy rules matched? │ No rule │ Default │ │ 3 │ Rule action = block? │ Critical PII │ BLOCK 403 │ │ 4 │ Rule action = redact? │ Mask + continue │ REDACT │ │ 5 │ Rule action = warn? │ Fire webhook │ WARN + pass │ │ 6 │ Daily budget OK? │ Exceeded │ BLOCK 429 │ │ 7 │ Rate limit OK? │ Exceeded │ BLOCK 429 │ │ 8 │ Default │ - │ PASS │ └────┴──────────────────────────┴─────────────────┴──────────────┘ ## Integrations 12 pre-configured integrations. Tamga plugs into your existing security and observability stack: %%{init: { 'theme': 'dark', 'themeVariables': { 'primaryColor': '#1e3a5f', 'primaryTextColor': '#dbeafe', 'primaryBorderColor': '#3b82f6', 'lineColor': '#6b7280', 'background': '#0f172a', 'mainBkg': '#1e293b' } }}%% graph TB subgraph "Identity Providers" Github[GitHub OAuth] SAML[SAML / OIDC
Enterprise] end subgraph "Tamga Core" Proxy[Tamga Proxy] Auth[Auth Layer
JWT + Bearer] end subgraph "SIEM / Security Tools" Splunk[Splunk HEC] Sentinel[Microsoft Sentinel] Elastic[Elastic / OpenSearch] Datadog[Datadog Logs] end subgraph "Notification" Slack[Slack Webhooks] Teams[MS Teams] PagerDuty[PagerDuty] Email[Email/SMTP] end subgraph "Observability" OTLP[OTLP Collector] Prometheus[Prometheus /metrics] Jaeger[Jaeger UI] end Github --> Auth SAML --> Auth Auth --> Proxy Proxy -.->|HEC events| Splunk Proxy -.->|Log Analytics| Sentinel Proxy -.->|JSON logs| Elastic Proxy -.->|datadog-go| Datadog Proxy -.->|webhook| Slack Proxy -.->|webhook| Teams Proxy -.->|events| PagerDuty Proxy -.->|smtp| Email Proxy -.->|traces| OTLP Proxy -.->|metrics| Prometheus OTLP --> Jaeger classDef idp fill:#1e3a5f,stroke:#3b82f6,color:#dbeafe classDef siem fill:#3a1f5f,stroke:#a855f7,color:#e9d5ff classDef notif fill:#3a2d0a,stroke:#f59e0b,color:#fef3c7 classDef obs fill:#0d3a3a,stroke:#14b8a6,color:#ccfbf1 class Github,SAML idp class Splunk,Sentinel,Elastic,Datadog siem class Slack,Teams,PagerDuty,Email notif class OTLP,Prometheus,Jaeger obs See `docs/architecture/` for per-service setup guides. ## Features | Category | Capability | Action | |---|---|---| | **PII Detection** | Credit card, TC Kimlik, IBAN, email, phone, IP (helps achieve KVKK, GDPR, PCI-DSS compliance by preventing raw PII/PCI from leaving your perimeter) | `REDACT` | | **Secret Detection** | AWS/GitHub/OpenAI keys, JWT, private keys, connection strings | `BLOCK` | | **Injection Detection** | Prompt injection, jailbreak, DAN-style attacks | `BLOCK` | | **Custom Entities** | Regex-defined patterns (customer IDs, file numbers) | `REDACT` / `WARN` | | **Competitor Watch** | Detect competitor mentions in prompts | `WARN` | | **Rate Limiting** | Per-API-key token bucket (requests/min, tokens/day) | `BLOCK` | | **Provider Control** | Allow/block specific LLM providers per policy | — | | **Body Limits** | Per-provider request size caps with `413` response | — | | **Policy Hot-Reload** | Edit YAML → reload in-place or via `POST /api/v1/policies/reload` | — | | **Event Bus** | Buffered pub/sub for metrics, logs, alerts, DB | async | | **REST API** | Stats, events, health, policy management | `:8443/api/v1` | | **Audit Logging** | Optional PostgreSQL persistence with full request telemetry | — | | **OpenTelemetry** | Jaeger tracing integration | optional | | **Mock Upstream** | Demo mode without real provider keys | `TAMGA_MOCK_UPSTREAM=true` | ## How Tamga Compares | Feature | Tamga | Cloud Services | Open-Source Gateways | Legacy DLP | |---------|-------|---------------|---------------------|------------| | **Self-hosted** | ✅ Full | ❌ Cloud-only | ✅ | ✅ | | **Turkish PII (TCKN, IBAN, VKN)** | ✅ Native | ⚠️ Partial | ❌ | ⚠️ Partial | | **KVKK / BDDK mapping** | ✅ Documented | ❌ | ❌ | ⚠️ Partial | | **Inline PII redaction (sub-ms)** | ✅ | ✅ | ⚠️ Tier-gated | ⚠️ HTTPS only | | **Multi-provider routing** | ✅ | ✅ | ✅ | ❌ | | **Hash-chain audit logs** | ✅ | ❌ | ⚠️ | Some | | **Open source** | ✅ AGPL-3.0 | ❌ | ✅ MIT | ❌ | | **Custom regex / entity** | ✅ | ❌ | ⚠️ | ✅ | | **Adversarial test suite published** | ✅ Public, 62+ vectors | ❌ | ❌ | ❌ | | **Stress test CI gate** | ✅ PR-blocking | ❌ | ❌ | ❌ | ## Cost Control & Budget Enforcement Track token spend per API key, team, and provider in real-time. Set hard budget caps to prevent runaway costs. | Control | Granularity | Behavior | |---------|-------------|----------| | Daily budget | Per API key | BLOCK 429 when exceeded | | Monthly budget | Per team | WARN webhook, then BLOCK | | Provider quota | Per provider | Failover to cheaper provider | | Per-request cap | Per API key | BLOCK requests above token threshold | Cost attribution by provider, model family, team (API key tagging), and user (`X-User-ID` header). Full dashboard with daily burn, MTD totals, per-model breakdown, and monthly projections. # Set $100/day budget for a team curl -X PUT $TAMGA_URL/api/v1/budgets/team_finance \ -H "X-Tamga-Admin-Key: $KEY" \ -d '{"daily_limit_usd":100,"action":"block"}' ## Real-World Use Cases ### Bank with Shadow AI (Primary fit) **Problem:** Employees pasting customer TC kimlik and IBAN into ChatGPT. KVKK fines and BDDK audit exposure. **Solution:** Tamga sits between the corporate proxy and LLM providers. Inline detection blocks TC/IBAN, redacts customer names, logs every attempt for BDDK audit. KVKK officer gets real-time webhook notification. **Result:** Zero PII leak to LLM providers; complete audit trail; compliance evidence ready for regulator review. ### SaaS Company Using Multiple LLMs Internally **Problem:** Engineering uses Copilot, sales uses ChatGPT Enterprise, support uses Claude. Three vendors, three dashboards, no unified cost view. **Solution:** Tamga as unified proxy. Single API key per team, daily budget caps, provider-agnostic policy enforcement. One dashboard for all LLM usage across the organization. **Result:** 30–40% cost reduction via budget enforcement and caching; unified audit trail; policy consistency across teams. ### Healthcare Provider with RAG Application **Problem:** RAG indexes patient records; risk of surfacing PHI in answers. Indirect prompt injection in uploaded documents. **Solution:** Tamga between RAG and LLM. Source-tagged content inspection on RAG chunks. Indirect injection detector flags suspicious payloads. PHI redaction on output before return to user. **Result:** HIPAA compliance pathway; auditable PHI handling; defense-in-depth against indirect injection. ## Tech Stack
| Layer | Technology |
|---|---|
| Core Proxy |
|
| Deep Analysis |
|
| Dashboard |
|
| Storage |
|
| Observability |
|
| Deployment |
|
Essential environment variables
| Variable | Default | Description | |---|---|---| | `TAMGA_PROXY_PORT` | `8443` | Proxy listen port | | `TAMGA_POLICY_PATH` | `./tamga-policy.yaml` | Policy file location | | `TAMGA_ADMIN_KEY` | — | Admin API auth key (required for protected routes) | | `TAMGA_DB_URL` | — | PostgreSQL DSN (empty = DB logging off) | | `REDIS_URL` | — | Redis connection string | | `TAMGA_ANALYZER_URL` | — | Analyzer service base URL | | `TAMGA_MAX_BODY_BYTES` | `1048576` | Max request body size (1 MB) | | `TAMGA_MOCK_UPSTREAM` | `false` | Demo mode without real providers | | `TAMGA_OTLP_ENDPOINT` | — | OpenTelemetry collector endpoint | | `ANTHROPIC_API_KEY` | — | Anthropic provider key | | `OPENAI_API_KEY` | — | OpenAI provider key | [Full reference →](proxy/README.md#ortam-değişkenleri-seçilmiş)Sample policy (YAML)
version: "1.0" name: "default-policy" rules: pii_detection: action: REDACT sensitivity: medium types: [credit_card, tc_kimlik, iban, email, phone_tr] secret_detection: action: BLOCK sensitivity: low types: [aws_access_key, github_token, openai_key, jwt_token] injection: action: BLOCK sensitivity: medium providers: allowed: [openai, anthropic, azure_openai, google_vertex] blocked: [] rate_limit: max_requests_per_minute: 60 max_tokens_per_day: 500000 action_on_exceed: BLOCK [Full policy reference →](proxy/tamga-policy.yaml)
Built by the Tamga team · GitHub
标签:DLL 劫持, EVTX分析, Go, Python, Ruby工具, 人工智能安全, 反向代理, 合规性, 大语言模型, 子域名突变, 搜索引擎查询, 数据脱敏, 无后门, 日志审计, 测试用例, 用户代理, 网络测绘, 请求拦截, 逆向工具, 隐私合规, 零日漏洞检测