{"id":28766265,"url":"https://github.com/flew1x/grpc-chaos-proxy","last_synced_at":"2026-05-15T21:37:22.321Z","repository":{"id":299136741,"uuid":"1001479429","full_name":"flew1x/grpc-chaos-proxy","owner":"flew1x","description":"Chaos-engineering for a gRPC zoo, all-in-one and without vendor-lock","archived":false,"fork":false,"pushed_at":"2025-06-14T21:35:18.000Z","size":2,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-14T22:32:30.782Z","etag":null,"topics":["go","golang","grpc","pentesting","proxy","testing"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/flew1x.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-13T12:59:50.000Z","updated_at":"2025-06-14T21:51:45.000Z","dependencies_parsed_at":"2025-06-14T22:32:36.397Z","dependency_job_id":"53dd0aac-6595-4f6f-9943-696a1232ab2d","html_url":"https://github.com/flew1x/grpc-chaos-proxy","commit_stats":null,"previous_names":["flew1x/grpc-chaos-proxy"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/flew1x/grpc-chaos-proxy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flew1x%2Fgrpc-chaos-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flew1x%2Fgrpc-chaos-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flew1x%2Fgrpc-chaos-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flew1x%2Fgrpc-chaos-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/flew1x","download_url":"https://codeload.github.com/flew1x/grpc-chaos-proxy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flew1x%2Fgrpc-chaos-proxy/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266037177,"owners_count":23867456,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang","grpc","pentesting","proxy","testing"],"created_at":"2025-06-17T12:00:34.217Z","updated_at":"2026-05-15T21:37:17.300Z","avatar_url":"https://github.com/flew1x.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# grpc-chaos-proxy\n\nChaos engineering for a gRPC zoo, all-in-one and without vendor lock-in.\n\n## Overview\n\n**grpc-chaos-proxy** is a tool for introducing chaos into your gRPC-based systems. It acts as a proxy between your gRPC clients and servers, allowing you to inject failures, delays, aborts, spamming, and other network anomalies to test the resilience of your microservices.\n\n## Features\n\n- Inject artificial delays and errors into gRPC traffic\n- Abort requests with configurable error codes and percentage\n- Simulate network latency (randomized min/max delay)\n- Spam requests to backend (for load/chaos testing)\n- Compose complex chaos actions (randomly pick from a set)\n- Flexible configuration via YAML files (see `configs/dev.yaml`)\n- Hot-reload config support\n- No vendor lock-in, fully open source\n\n## Installation\n\n### Prerequisites\n\n- Go 1.20+ installed\n- (Optional) Docker for containerized usage\n\n### Build from Source\n\n```bash\ngit clone https://github.com/flew1x/grpc-chaos-proxy\ncd grpc-chaos-proxy\nmake build\n```\n\nThe binary will be available at `bin/proxy`.\n\n## Quick Start\n\n### 1. Prepare a Configuration\n\nExample (`configs/dev.yaml`):\n\n```yaml\nlistener:\n  address: \"localhost:5050\"\n\nbackend:\n  address: \"localhost:5010\"\n\nrules:\n  - name: \"spammer-test\"\n    match:\n      service: \"protoann.Service\"\n      method_regex: \"^GetByIinOrBin$\"\n    action:\n      spammer:\n        count: 5\n        delay: { min_ms: 1000, max_ms: 5000 }\n\n  - name: \"chaos-test\"\n    match:\n      service: \"protoann.Service\"\n      method_regex: \"^GetByIinOrBin$\"\n    action:\n      chaos:\n        actions:\n          - delay: { min_ms: 100, max_ms: 300 }\n          - abort:\n              code: \"UNAVAILABLE\"\n              percentage: 50\n\n  - name: \"abort-test\"\n    match:\n      service: \"protoann.Service\"\n      method_regex: \"^GetByIinOrBin$\"\n    action:\n      abort:\n        code: \"UNAVAILABLE\"\n        percentage: 50\n\n  - name: \"delay-test\"\n    match:\n      service: \"protoann.Service\"\n      method_regex: \"^GetByIinOrBin$\"\n    action:\n      delay: { min_ms: 100, max_ms: 300}\n\n  - name: \"header-inject-test\"\n    match:\n      service: \"protoann.Service\"\n      method_regex: \"^GetByIinOrBin$\"\n    action:\n      header:\n        headers:\n          x-custom:\n            prefix: \"pre-\"\n            suffix: \"-suf\"\n            values: [\"val1\", \"val2\"]\n          x-another: \"static-value\"\n        allowlist: [\"x-custom\", \"x-another\"]\n        direction: \"inbound\" # or \"outbound\", or \"both\"\n\n  - name: \"ratelimit-test\"\n    match:\n      service: \"protoann.Service\"\n      method_regex: \"^GetByIinOrBin$\"\n    action:\n      ratelimit:\n        rate_limit: 5    # allowed requests per second\n        burst_size: 2    # additional burst capacity\n```\n\n### 2. Start the Proxy\n\n```bash\n./bin/proxy --config configs/dev.yaml\n```\n\n### 3. Point Your gRPC Client\n\nChange your gRPC client to connect to the proxy (`localhost:5050`), which will forward requests to your real server (`localhost:5010`) and inject chaos as configured.\n\n## Rule Types \u0026 Examples\n\n### Delay\nInjects a random delay before forwarding the request.\n```yaml\n- name: \"delay-test\"\n  match:\n    service: \"protoann.Service\"\n    method_regex: \"^GetByIinOrBin$\"\n  action:\n    delay: { min_ms: 100, max_ms: 300 }\n```\n\n### Abort\nAborts requests with a given gRPC code in a percentage of cases.\n```yaml\n- name: \"abort-test\"\n  match:\n    service: \"protoann.Service\"\n    method_regex: \"^GetByIinOrBin$\"\n  action:\n    abort:\n      code: \"UNAVAILABLE\"\n      percentage: 50\n```\n\n### Spammer\nSends multiple requests to the backend, optionally with delay between them.\n```yaml\n- name: \"spammer-test\"\n  match:\n    service: \"protoann.Service\"\n    method_regex: \"^GetByIinOrBin$\"\n  action:\n    spammer:\n      count: 5\n      delay: { min_ms: 1000, max_ms: 5000 }\n```\n\n### Chaos (Composite)\nRandomly applies one of the listed actions.\n```yaml\n- name: \"chaos-test\"\n  match:\n    service: \"protoann.Service\"\n    method_regex: \"^GetByIinOrBin$\"\n  action:\n    chaos:\n      actions:\n        - delay: { min_ms: 100, max_ms: 300 }\n        - abort:\n            code: \"UNAVAILABLE\"\n            percentage: 50\n```\n\n### Network\nSimulates network failures: packet loss (loss) and artificial delay (throttle).\n\n```yaml\n- name: \"network-test\"\n  match:\n    service: \"protoann.Service\"\n    method_regex: \"^GetByIinOrBin$\"\n  action:\n    network:\n      loss_percentage: 20      # probability to drop the request, %\n      throttle_ms: 200         # artificial delay in milliseconds\n```\n\n- `loss_percentage`: probability that the request will be \"lost\" (not forwarded to the backend)\n- `throttle_ms`: delay (in ms) before forwarding the request to the backend\n\n### Header\nInjects, modifies, or removes gRPC metadata headers. Supports:\n- Adding/modifying headers with prefix/suffix and multiple values\n- Allowlist: keep only specified headers, remove all others\n- Direction: apply only on inbound, outbound, or both traffic\n\nExample:\n```yaml\n- name: \"header-test\"\n  match:\n    service: \"protoann.Service\"\n    method_regex: \"^GetByIinOrBin$\"\n  action:\n    header:\n      headers:\n        x-custom:\n          prefix: \"pre-\"\n          suffix: \"-suf\"\n          values: [\"val1\", \"val2\"]\n        x-another: \"static-value\"\n      allowlist: [\"x-custom\", \"x-another\"]\n      direction: \"inbound\" # or \"outbound\", or \"both\"\n```\n- `headers`: map of header names to modification rules. Each rule can have `prefix`, `suffix`, and a list of `values` (or a single string value).\n- `allowlist`: if set, only these headers will be kept, all others will be removed.\n- `direction`: controls when the injection is applied: `inbound`, `outbound`, or `both` (default).\n\n### RateLimit\nLimits the number of requests per second (token bucket algorithm). Useful for simulating backend rate limiting or throttling.\n\n```yaml\n- name: \"ratelimit-test\"\n  match:\n    service: \"protoann.Service\"\n    method_regex: \"^GetByIinOrBin$\"\n  action:\n    ratelimit:\n      rate_limit: 5    # allowed requests per second\n      burst_size: 2    # additional burst capacity\n```\n- `rate_limit`: maximum number of requests per second.\n- `burst_size`: how many extra requests can be handled in a burst (optional, default 0).\n\nIf the limit is exceeded, the request will be rejected with a rate limit error.\n\n### Disconnect\nSimulates random connection drops (disconnects) by returning a gRPC error with a specified probability. Useful for testing client resilience to network failures.\n\nExample:\n```yaml\n- name: \"disconnect-test\"\n  match:\n    service: \"protoann.Service\"\n    method_regex: \"^GetByIinOrBin$\"\n  action:\n    disconnect:\n      percentage: 20  # probability (0-100) to simulate a disconnect\n```\n- `percentage`: probability (0-100) that the request will be forcibly disconnected (default: 0).\n\nIf triggered, the proxy returns a gRPC error with code `UNAVAILABLE` and message `chaos disconnect injected`.\n\n### Code\nInjects a custom gRPC error code with advanced options. Useful for simulating specific error scenarios, custom error messages, and more.\n\nExample:\n```yaml\n- name: \"code-test\"\n  match:\n    service: \"protoann.Service\"\n    method_regex: \"^GetByIinOrBin$\"\n  action:\n    code:\n      code: \"UNAVAILABLE\"         # gRPC code to return (see codes.go for all options)\n      message: \"custom error\"     # custom error message (optional)\n      percentage: 30              # probability (0-100) to inject error (optional)\n      delay_ms: 100               # delay before returning error (ms, optional)\n      metadata:\n        x-debug: \"true\"           # custom metadata to add to response (optional)\n      only_on_methods: [\"GetByIinOrBin\"] # apply only to these methods (optional)\n      repeat_count: 2             # how many times to repeat error (optional)\n```\n- `code`: gRPC error code to return (e.g., UNAVAILABLE, INTERNAL, NOT_FOUND, etc.)\n- `message`: custom error message (optional)\n- `percentage`: probability (0-100) to inject error (optional, default: 100)\n- `delay_ms`: delay before returning error in milliseconds (optional)\n- `metadata`: map of metadata keys/values to add to the response (optional)\n- `only_on_methods`: list of method names to apply the rule to (optional)\n- `repeat_count`: how many times to repeat the error for the same request (optional)\n\nIf triggered, the proxy returns a gRPC error with the specified code and message, and can add custom metadata or delay the response.\n\n### Script\nExecutes a custom shell script (sh/bash) as part of the chaos action. Useful for dynamic, programmable chaos scenarios, integration with external systems, or advanced request/response mutation.\n\nExample:\n```yaml\n- name: \"script-test\"\n  match:\n    service: \"protoann.Service\"\n    method_regex: \"^GetByIinOrBin$\"\n  action:\n    script:\n      language: sh\n      source: |\n        if [ \"$1\" = \"fail\" ]; then\n          echo \"X-CHAOS-ERROR: custom script error\"\n          exit 1\n        fi\n        echo \"X-CHAOS-HEADER: x-script=ok\"\n      args: [\"fail\"]\n      timeout_ms: 500\n      env:\n        FOO: \"bar\"\n```\n- `language`: script language (currently supports `sh` or `bash`)\n- `source`: script source code (string or multiline)\n- `args`: arguments to pass to the script (optional)\n- `timeout_ms`: script execution timeout in milliseconds (optional)\n- `env`: environment variables for the script (optional)\n\n**Special output handling:**\n- If the script outputs a line starting with `X-CHAOS-ERROR:`, the proxy will treat it as an error and return it to the client.\n- If the script outputs a line starting with `X-CHAOS-HEADER: key=value`, the proxy will add this header to the response metadata.\n\nThis allows you to implement custom, programmable chaos logic directly in your configuration.\n\n## Configuration Reference\n\n- `listener.address`: Address to listen for incoming gRPC requests (e.g., `localhost:5050`)\n- `backend.address`: Address of the real gRPC server (e.g., `localhost:5010`)\n- `rules`: List of rules to apply\n  - `name`: Rule name (for logging)\n  - `match.service`: Service name to match (exact, case-insensitive)\n  - `match.method_regex`: Regex for method name\n  - `action`: One of:\n    - `delay`: `{ min_ms: int, max_ms: int }`\n    - `abort`: `{ code: string, percentage: int }`\n    - `spammer`: `{ count: int, delay: { min_ms: int, max_ms: int } }`\n    - `chaos`: `{ actions: [ ... ] }` (list of actions)\n    - `network`: `{ loss_percentage: int, throttle_ms: int }`\n    - `header`: `{ headers: { ... }, allowlist: [ ... ], direction: \"inbound|outbound|both\" }`\n    - `ratelimit`: `{ rate_limit: int, burst_size: int }`\n    - `disconnect`: `{ percentage: int }`\n    - `code`: `{ code: string, message: string, percentage: int, delay_ms: int, metadata: { ... }, only_on_methods: [ ... ], repeat_count: int }`\n    - `script`: `{ language: string, source: string, args: [ ... ], timeout_ms: int, env: { ... } }`\n\n## Hot Reload\n\nThe proxy supports hot-reloading of the config file. Update the YAML file and the proxy will reload rules automatically.\n\n## Contributing\n\nContributions are welcome! Please open issues or pull requests.\n\n## License\n\nMIT License. See [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflew1x%2Fgrpc-chaos-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflew1x%2Fgrpc-chaos-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflew1x%2Fgrpc-chaos-proxy/lists"}