{"id":38329267,"url":"https://github.com/evo-cloud/spf","last_synced_at":"2026-01-17T02:48:43.417Z","repository":{"id":57709264,"uuid":"285751747","full_name":"evo-cloud/spf","owner":"evo-cloud","description":"Secure Port Forwarder","archived":false,"fork":false,"pushed_at":"2020-09-19T01:38:06.000Z","size":48,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-06-21T12:55:39.819Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/evo-cloud.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}},"created_at":"2020-08-07T06:08:47.000Z","updated_at":"2020-09-19T01:38:08.000Z","dependencies_parsed_at":"2022-09-13T00:34:25.282Z","dependency_job_id":null,"html_url":"https://github.com/evo-cloud/spf","commit_stats":null,"previous_names":["evo-cloud/epd"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/evo-cloud/spf","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evo-cloud%2Fspf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evo-cloud%2Fspf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evo-cloud%2Fspf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evo-cloud%2Fspf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/evo-cloud","download_url":"https://codeload.github.com/evo-cloud/spf/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evo-cloud%2Fspf/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28492590,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T02:39:23.645Z","status":"ssl_error","status_checked_at":"2026-01-17T02:34:19.649Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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-01-17T02:48:43.309Z","updated_at":"2026-01-17T02:48:43.385Z","avatar_url":"https://github.com/evo-cloud.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Secure Port Forwarder\n\nThis is a remote port forwarder based on SSH protocol (`ssh -R`).\nIt only supports remote port forwarding, but not the rest of SSH features (no session/channel is supported),\nso it's safer than running a full featured SSH server on a public network.\n\nWith Secure Port Forwarder running on a public network,\na server behind a firewall can be exposed to the public network using:\n\n```shell\nssh -N -R https/www.example.com:localhost:8080 user@spf.example.com\n```\n\nHere assuming Secure Port Forwarder is running on `spf.example.com` on regular SSH port `22`,\nand the server behind the firewall is running on `localhost:8080`.\nThe `ssh` command asks Secure Port Forwarder to forward `www.example.com:80` and rely it to `localhost:8080`.\n\nHowever Secure Port Forwarder doesn't exposing the specified DNS and port to the public network.\nInstead, it only opens a random TCP port on `localhost` and forwards connections to the SSH client.\nUser must provide an endpoint setup script for setting up `www.example.com:80` on some proxy server\n(e.g. [traefik](https://github.com/containous/traefik)).\n\n## Usage\n\nLaunch `spfd` without arguments to use default configurations:\n\n- `-addr=:2022`: listen on `:2022` as SSH server address;\n- Use host keys from `/etc/ssh`;\n- Use `~/.ssh/authorized_keys` for authorized keys;\n- `-bind-addr=localhost`: open random TCP port as requested on `localhost`;\n\nIn addition to that, specifying `-setup-cmd=PROGRAM` to use `PROGRAM` for setting up a DNS based reverse proxy.\n\nFor example, when using [traefik](https://github.com/containous/traefik), a shell script can be used to configure it\nfor forwarding the request on a specific DNS to a localhost port.\nThe `PROGRAM` is invoked as:\n\n```\nPROGRAM open|close tcp|sock ENDPOINT local-host:local-port\n```\n\n- `open` is used to ask the script to start forwarding from `ENDPOINT` to `local-host:local-port`;\n- `close` is used to ask the script to stop forwarding from `ENDPOINT`.\n\n`ENDPOINT` is defined for\n- `tcp`: `public-host:public-port`\n- `sock`: a unix socket path, it's recommended to be `scheme/DNS`, e.g. `https/example.com`. \n\nAccording to `-bind-address=A.B.C.D` when launching `spfd`, and the SSH client command line, e.g.\n\n```shell\nssh -N -R https/www.example.com:localhost:8080 user@spf.example.com\n```\n\nIt will call the setup program as\n\n```\nPROGRAM open sock https/www.example.com A.B.C.D:port\n```\n\n## The Client\n\n`spfc` is a client to work with server-side `spfd` as an HTTP reverse proxy.\nIt watches dynamic backend states and exposes/unexposes endpoints accordingly.\nThe currently supported backend states providers are:\n\n- `files`: Watches a list of directories (not sub-directories) and loads backend configurations from text files;\n- `k8s`: Run `spfc` as a Kubernetes controller which watches `Service` resources with annotation `spf.evo-cloud/endpoint` and exposes the annotation value as the endpoint on the server side.\n\n### Files Provider\n\nThe format of a file containing backend states is:\n\n```\nID ENDPOINT BACKEND-URL\n```\n\nE.g.\n\n```\na https/a.example.com http://localhost:8080\n```\n\nEmpty lines and lines starting with `#` are ignored.\nAll the lines from all discovered files are merged to create the final list of backend states.\nUse the following command line flags to enable this provider:\n\n- `--files-dirs`: a semi-colon separated list of directory paths to watch for files and this must be specified to enable this provider;\n- `--files-glob`: a pattern to filter file names. The default value is `*` (matching all files).\n\n### Kubernetes Provider\n\nSimply put `--k8s` on the command line to enable this provider.\nIt watches `Service` resource with annotation `spf.evo-cloud/endpoint`.\nThe value of the annotation is used as `ENDPOINT` on the server side.\nThe format should be `SCHEME/DNS`. `SCHEME` can be `https` or `http`.\n\nThe first `Port` in the `Service` will be used as backend server port.\nIf no `Port` is present, default HTTP port `80` will be used.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevo-cloud%2Fspf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevo-cloud%2Fspf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevo-cloud%2Fspf/lists"}