{"id":43727242,"url":"https://github.com/igorrius/tcp-sproxy","last_synced_at":"2026-02-05T09:10:17.264Z","repository":{"id":308938665,"uuid":"1034511580","full_name":"igorrius/tcp-sproxy","owner":"igorrius","description":"TCP client-server based on streaming transport ","archived":false,"fork":false,"pushed_at":"2025-10-09T07:48:57.000Z","size":91,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-13T12:25:40.055Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/igorrius.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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-08-08T14:03:49.000Z","updated_at":"2025-10-10T12:20:05.000Z","dependencies_parsed_at":"2025-08-08T21:49:15.702Z","dependency_job_id":null,"html_url":"https://github.com/igorrius/tcp-sproxy","commit_stats":null,"previous_names":["igorrius/tcp-sproxy"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/igorrius/tcp-sproxy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorrius%2Ftcp-sproxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorrius%2Ftcp-sproxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorrius%2Ftcp-sproxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorrius%2Ftcp-sproxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/igorrius","download_url":"https://codeload.github.com/igorrius/tcp-sproxy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igorrius%2Ftcp-sproxy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29117920,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T05:31:32.482Z","status":"ssl_error","status_checked_at":"2026-02-05T05:31:29.075Z","response_time":65,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2026-02-05T09:10:15.649Z","updated_at":"2026-02-05T09:10:17.248Z","avatar_url":"https://github.com/igorrius.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tcp-sproxy (NATS TCP Stream Proxy)\n\nA minimal TCP stream proxy that tunnels arbitrary TCP connections over NATS. It consists of:\n- A server that accepts proxy requests via NATS and connects to the target TCP service.\n- A client that listens on a local TCP port and forwards each incoming connection through NATS to the server, which then talks to the target.\n\nThis is useful when direct TCP connectivity to a service is not possible, but NATS connectivity is available.\n\n## Status\nExperimental. Suitable for demos and experiments. Security, auth, and advanced features are out of scope for now.\n\n## How it works (high level)\n- Control plane:\n  - Client requests a new proxy connection by sending a NATS request to subject `proxy.request` with metadata: `remote_host` and `remote_port`.\n  - Server replies with a generated `connection ID`.\n- Data plane:\n  - Client -\u003e Server bytes are published to `p.data.to_server.{connectionID}`.\n  - Server -\u003e Client bytes are published to `p.data.to_client.{connectionID}`.\n- The server maintains a TCP connection to the remote service and relays bytes between it and the client over NATS.\n\nInternally, messages are serialized as JSON using a simple `transport.Message` structure.\n\n## Repository layout\n- cmd/server: NATS proxy server\n- cmd/client: NATS proxy client\n- internal/...: domain, use cases, NATS transport, and in-memory repository\n- integration_tests: docker-compose setup and a Redis-based end‑to‑end test\n\n## Requirements\n- Go 1.24+\n- A running NATS server (e.g., `nats:2.9-alpine`)\n- Docker and Docker Compose (for integration tests or containerized runs)\n\n## Build\nBuild both binaries locally:\n\n```bash\ngo build -o bin/nats-proxy-server ./cmd/server\ngo build -o bin/nats-proxy-client ./cmd/client\n```\n\nOr run directly:\n\n```bash\ngo run ./cmd/server --help\ngo run ./cmd/client --help\n```\n\n## Quick start locally (Redis example)\n1) Start NATS:\n\n```bash\ndocker run --rm -p 4222:4222 --name nats nats:2.9-alpine\n```\n\n2) Start Redis locally for the demo:\n\n```bash\ndocker run --rm -p 6379:6379 --name redis redis:7-alpine\n```\n\n3) Start the proxy server (in another terminal):\n\n```bash\nbin/nats-proxy-server --nats-url nats://127.0.0.1:4222 --log-level info\n```\n\n4) Start the proxy client to expose a local port that forwards to Redis via NATS:\n\n```bash\nbin/nats-proxy-client \\\n  --nats-url nats://127.0.0.1:4222 \\\n  --listen-addr 127.0.0.1:6380 \\\n  --remote-addr 127.0.0.1:6379 \\\n  --proxy-addr localhost:8081  # currently informational/reserved\n```\n\n5) Test with redis-cli:\n\n```bash\nredis-cli -h 127.0.0.1 -p 6380 PING\nredis-cli -h 127.0.0.1 -p 6380 SET key value\nredis-cli -h 127.0.0.1 -p 6380 GET key\n```\n\nIf everything is wired, you should see PONG and value replies proxied over NATS.\n\n## Configuration\nBoth binaries use Cobra + Viper. You can configure via flags, env vars, or config files.\n\n### Server (nats-proxy-server)\n- Flags:\n  - `--nats-url` (default `nats://localhost:4222`)\n  - `--listen-addr` (default `:8080`) — currently not used by the server\n  - `--log-level` (debug|info|warn|error; default `info`)\n  - `--config` (path to config file; default search: `./` then `$HOME`, file name `.nats-proxy-server.*`)\n- Environment:\n  - `NATS_URL` maps to `nats.url`\n  - `LOG_LEVEL` maps to `log.level`\n- Example YAML (e.g., `.nats-proxy-server.yaml`):\n\n```yaml\nnats:\n  url: nats://localhost:4222\nlog:\n  level: info\n```\n\n### Client (nats-proxy-client)\n- Flags:\n  - `--nats-url` (default `nats://localhost:4222`)\n  - `--listen-addr` (default `0.0.0.0:8082`) — local TCP listen address\n  - `--remote-addr` (default `redis:6379`) — target service address the server will dial\n  - `--proxy-addr` (default `proxy-server:8081`) — currently informational/reserved in NATS transport\n  - `--log-level` (debug|info|warn|error; default `info`)\n  - `--config` (path to config file; default search: `./` then `$HOME`, file name `.nats-proxy-client.*`)\n- Environment:\n  - `NATS_URL` → `nats.url`\n  - `LISTEN_ADDR` → `client.listen_addr`\n  - `REMOTE_ADDR` → `client.remote_addr`\n  - `PROXY_ADDR` → `client.proxy_addr`\n  - `LOG_LEVEL` → `log.level`\n- Example YAML (e.g., `.nats-proxy-client.yaml`):\n\n```yaml\nnats:\n  url: nats://localhost:4222\nclient:\n  listen_addr: 0.0.0.0:8082\n  remote_addr: redis:6379\n  proxy_addr: proxy-server:8081\nlog:\n  level: info\n```\n\n## Docker\n- Server-only image (root Dockerfile):\n\n```bash\ndocker build -t tcp-sproxy-server -f Dockerfile .\n# Then run with a NATS_URL env variable\n# NOTE: The Dockerfile exposes 8080 and defines a healthcheck path; the server does not expose an HTTP endpoint.\ndocker run --rm --network host -e NATS_URL=nats://127.0.0.1:4222 tcp-sproxy-server\n```\n\n- Dev/integration image (contains both server and client):\n\n```bash\ndocker build -t tcp-sproxy-bundle -f integration_tests/build/Dockerfile .\n```\n\n## Tests\n- Unit tests:\n\n```bash\ngo test ./...\n```\n\n- Integration test (Redis through the proxy using Docker Compose):\n\n```bash\n# Using Makefile\nmake test-integration\n\n# Or manually\ndocker-compose -f integration_tests/docker-compose.yml up -d --build\n# the test-runner service will execute integration tests\n# when finished\ndocker-compose -f integration_tests/docker-compose.yml down\n```\n\n**Note**: Integration tests require the following ports to be available on the host:\n- `4222` - NATS messaging\n- `6379` - Redis database\n- `8080`, `8081` - Proxy server\n- `8082` - Proxy client\n\nIf these ports are already in use, you'll need to either stop the conflicting services or modify the port mappings in `integration_tests/docker-compose.yml`.\n\n## Continuous Integration\n\nThis project uses GitHub Actions for automated testing:\n\n### Unit Tests\n- **Workflow**: `.github/workflows/test.yml`\n- **Triggers**: Pull requests and pushes to `main`/`master` branches\n- **Features**:\n  - Runs on Go 1.24\n  - Executes `go test` with race detection\n  - Generates code coverage reports\n  - Uploads coverage to Codecov\n  - Caches Go modules for faster builds\n\n### Integration Tests\n- **Workflow**: `.github/workflows/integration-test.yml`\n- **Triggers**: Manual dispatch, daily schedule (2 AM UTC), pushes to `main`/`master`\n- **Features**:\n  - Runs Docker Compose-based integration tests via `make test-integration`\n  - Automatically spins up Redis, NATS, proxy server, and proxy client containers\n  - Executes end-to-end Redis proxy tests\n  - No manual service setup required - all dependencies managed by Docker Compose\n\nBoth workflows ensure code quality and functionality across different scenarios.\n\n## Logging\nBoth components use logrus. Levels: `debug`, `info`, `warn`, `error` (set via `--log-level` or `LOG_LEVEL`).\n\n## Notes \u0026 Limitations\n- No authentication, rate limiting, or encryption provided by this project. Use NATS security features and network controls as appropriate.\n- The `--proxy-addr` on the client is currently reserved/informational in the NATS transport implementation.\n- The server does not currently expose an HTTP endpoint (despite the Dockerfile healthcheck example).\n\n## License\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figorrius%2Ftcp-sproxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Figorrius%2Ftcp-sproxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figorrius%2Ftcp-sproxy/lists"}