{"id":47009412,"url":"https://github.com/internetee/epp_proxy","last_synced_at":"2026-03-11T20:39:55.587Z","repository":{"id":39695848,"uuid":"183406248","full_name":"internetee/epp_proxy","owner":"internetee","description":"Proxy engine to translate EPP connections into HTTP calls","archived":false,"fork":false,"pushed_at":"2026-02-16T10:04:11.000Z","size":1086,"stargazers_count":5,"open_issues_count":19,"forks_count":4,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-02-16T17:41:14.242Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/internetee.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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-04-25T09:52:43.000Z","updated_at":"2026-02-16T10:04:15.000Z","dependencies_parsed_at":"2024-04-29T09:37:08.689Z","dependency_job_id":"dbee8490-bd57-4e6c-90e1-39ef49f4c187","html_url":"https://github.com/internetee/epp_proxy","commit_stats":null,"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/internetee/epp_proxy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internetee%2Fepp_proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internetee%2Fepp_proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internetee%2Fepp_proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internetee%2Fepp_proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/internetee","download_url":"https://codeload.github.com/internetee/epp_proxy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/internetee%2Fepp_proxy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30399657,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-11T18:46:22.935Z","status":"ssl_error","status_checked_at":"2026-03-11T18:46:17.045Z","response_time":84,"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-03-11T20:39:54.938Z","updated_at":"2026-03-11T20:39:55.582Z","avatar_url":"https://github.com/internetee.png","language":"Erlang","readme":"epp_proxy\n=====\n\n[![Build Status](https://travis-ci.org/internetee/epp_proxy.svg?branch=master)](https://travis-ci.org/internetee/epp_proxy)\n\nAn application that translates EPP over TCP connection into set of predefined HTTP calls.\n\nServes as direct replacement for mod_epp (https://github.com/mod-epp/mod-epp), and tries to\nemulate it's behaviour to the biggest possible extent.\n\nAside from the standard library of Erlang/OTP, it uses hackney for making HTTP requests\nand lager for logging.\n\nCode style\n----\nWe enforce the style from Erlang's own configuration. You can use the rebar3_fmt plugin to do it for you:\n\n    $ rebar3 fmt\n\n\nDesign\n----\n\nTranslation of EPP calls\n-----\nThe application listens on predefined TCP port for formatted EPP frames and translates them into\nHTTP requests according to the following matrix. Application performs regex search for clTRID and an\nXPATH search for command name. It does not check against any XSD schema.\n\n| EPP Command | HTTP request                     | Parameters                 | Headers                                                             | Payload Type   | Cookies |\n|-------------|----------------------------------|----------------------------|---------------------------------------------------------------------|----------------|---------|\n| hello       | `GET /epp_session_url/hello`     |                            |  SSL-CLIENT-CERT, SSL-CLIENT-S-DN-CN, User-Agent, X-Forwarded-for   |                | session |\n| login       | `POST /epp_session_url/login`    | `raw_frame, frame, clTRID` |  SSL-CLIENT-CERT, SSL-CLIENT-S-DN-CN, User-Agent, X-Forwarded-for   | form/multipart | session |\n| logout      | `POST /epp_session_url/logout`   | `raw_frame, frame, clTRID` |  SSL-CLIENT-CERT, SSL-CLIENT-S-DN-CN, User-Agent, X-Forwarded-for   | form/multipart | session |\n| poll        | `POST /epp_command_url/poll`     | `raw_frame, frame, clTRID` |  SSL-CLIENT-CERT, SSL-CLIENT-S-DN-CN, User-Agent, X-Forwarded-for   | form/multipart | session |\n| check       | `POST /epp_command_url/check`    | `raw_frame, frame, clTRID` |  SSL-CLIENT-CERT, SSL-CLIENT-S-DN-CN, User-Agent, X-Forwarded-for   | form/multipart | session |\n| info        | `POST /epp_command_url/info`     | `raw_frame, frame, clTRID` |  SSL-CLIENT-CERT, SSL-CLIENT-S-DN-CN, User-Agent, X-Forwarded-for   | form/multipart | session |\n| create      | `POST /epp_command_url/create`   | `raw_frame, frame, clTRID` |  SSL-CLIENT-CERT, SSL-CLIENT-S-DN-CN, User-Agent, X-Forwarded-for   | form/multipart | session |\n| delete      | `POST /epp_command_url/delete`   | `raw_frame, frame, clTRID` |  SSL-CLIENT-CERT, SSL-CLIENT-S-DN-CN, User-Agent, X-Forwarded-for   | form/multipart | session |\n| renew       | `POST /epp_command_url/renew`    | `raw_frame, frame, clTRID` |  SSL-CLIENT-CERT, SSL-CLIENT-S-DN-CN, User-Agent, X-Forwarded-for   | form/multipart | session |\n| transfer | `POST /epp_command_url/transfer` | `raw_frame, frame, clTRID` |  SSL-CLIENT-CERT, SSL-CLIENT-S-DN-CN, User-Agent, X-Forwarded-for   | form/multipart | session |\n| update      | `POST /epp_command_url/update`   | `raw_frame, frame, clTRID` |  SSL-CLIENT-CERT, SSL-CLIENT-S-DN-CN, User-Agent, X-Forwarded-for   | form/multipart | session |\n| ANY (error) | `GET /epp_error_url`             | `msg, code, clTRID`        |  SSL-CLIENT-CERT, SSL-CLIENT-S-DN-CN, User-Agent, X-Forwarded-for   | query params   | session |\n\nError route is used in case EPP frame is malformed.\n\nThe application performs TLS handshake, checks certficate against provided revocation list and acts as\nTLS termination proxy, passing on the certificate information downstream as HTTP headers. It also passes\non the client IP address.\n\nSupervision Tree\n-----\nThe application leverages OTP to isolate EPP clients from one another, each connection is owned by its own process. There are two processes that\naccept the connections and spin off workers, those are supervised in \"one for one\" strategy.\n\nBuild\n-----\nYou need Erlang/OTP release 21 and Rebar3 to build it. No other versions than 21 were tested.\n\n    $ rebar3 compile\n\nepp_proxy should be deployed as a self-contained Erlang application (release). You can create one\nwith one of the following commands:\n\n```bash\n$ rebar3 release # Creates a release locally.\n$ rebar3 tar # Creates an archive that can be shipped to another machine\n$ rebar3 as prod release tar # Combines the steps above into single one, uses production profile.\n```\n\n### Creating and installing Releases\n\nThe application is configured to automatically create releases based on git tags. After you develop\na new functionality, you can create a release tag on Github.\n\nYou can then use appup to generate an upgrade path from currently running release to the new one.\nAssuming that a release currently running is v0.1.0, and you want to upgrade to v0.1.1, this is how\nthe process looks like:\n\n```sh\n$ git checkout tags/v0.1.0 # Check out the older version.\n$ rebar3 as prod release # Create the currently in use release, as it could have been deleted or corrupted in any way.\n$ git checkout tags/v0.1.1\n$ rebar3 as prod do release, appup generate --previous_version 0.1.0, relup, tar # Generate upgrade path, and then package it.\n```\n\n#### Installating\n\nYou can copy the archive with 0.1.1 to your target machine(s), and then execute:\n\n```sh\n$ ./bin/epp_proxy install 0.1.1 # Install the new version and marks it as permanent.\n```\n\nFrom there, you can either upgrade in place or restart into the new release.\n\n```sh\n$ ./bin/epp_proxy upgrade 0.1.1 # Upgrade in place.\n$ ./bin/epp_proxy reboot # Reboot the VM completely into the new permanent release.\n```\n\nConfiguration\n-----\nConfiguration for the application tries to emulate the mod_epp configuration as close as possible\nto make migration easier. The configuration is placed in `config/sys.config` file, it takes a format\nof Erlang property list.\n\n*Configuration variables*\n\n| Variable name        | Expected values                    | Apache equivalent     | Definition\n-----------------------|------------------------------------|-----------------------|--------------------------------------------\n| `dev_mode`           | `true`, `false`                    | None                  | Enables TCP access without TLS.\n| `tls_port`           | `700`                              | Listen                | At which port should we open a TLS socket. Default is 700.\n| `tcp_port`           | `70000`                            | Listen                | At which port should we open a TCP socket. Only in `dev_mode`.\n| `epp_session_url`    | `https://example.com/epp/session`  | EppSessionRoot        | HTTP address of the session endpoints including schema and port.\n| `epp_command_url`    | `https://example.com/epp/command`  | EppCommandRoot        | HTTP address of the command endpoints including schema and port.\n| `epp_error_url`      | `https://example.com/epp/error`    | EppErrorRoot          | HTTP address of the error endpoints including schema and port.\n| `cacertfile_path`    | `/opt/ca/ca.crt.pem`               | SSLCACertificateFile  | Where is the client root CA located. Can be inside apps/epp_proxy/priv or absolute path.\n| `certfile_path`      | `/opt/ca/server.crt.pem`           | SSLCertificateFile    | Where is the server certificate located. Can be inside apps/epp_proxy/priv or absolute path.\n| `keyfile_path`       | `/opt/ca/server.key.pem`           | SSLCertificateKeyFile | Where is the server key located. Can be inside apps/epp_proxy/priv or absolute path.\n| `crlfile_path`       | `/opt/ca/crl.pem`                  | SSLCARevocationFile   | Where is the CRL file located. Can be inside apps/epp_proxy/priv or absolute path. When not set, not CRL check is performed.\n\n\nMigrating from mod_epp\n----\n\nChecklist of steps to perform if you want to migrate from mod_epp, but still use Apache to be a reverse proxy.\n\n1. Remove SSL-CLIENT-S-DN-CN and SSL-CLIENT-CERT headers from Apache. Epp_proxy takes care of those.\n2. Install this project to desired location.\n3. Ensure that the user who will run epp_proxy has access to all certificate files.\n4. Set up syslog in `config/sys.config`.\n5. If you do not feel comfortable using Erlang configuration file, you can use command line arguments and flags in format of `/epp_proxy/rel/bin/epp_proxy -epp_proxy tls_port 444`, where `-epp_proxy` is name of application,\n   followed by configuration parameter name and value.\n\nTesting\n----\nThe application comes with test suite written with common_test. For integration\ntests, there is a small Roda application located in `apps/epp_proxy/priv/test_backend_app`.\nIt has been written with Ruby 3.2.2.\n\nThere is also a number of generated ssl certificates that are used only for testing. Those are\nvalid until 2029 and they are located in `apps/epp_proxy/priv/test_ca`. The password for test CA\nis `password`.\n\nYou need to start the backend application before running the test suite. To start it as a deamon,\nfrom the root folder of the project, execute:\n\n```bash\n$ /bin/bash -l -c \"cd apps/epp_proxy/priv/test_backend_app \u0026\u0026 bundle install\"\n$ /bin/bash -l -c \"cd apps/epp_proxy/priv/test_backend_app \u0026\u0026 bundle exec rackup --pid pidfile -D\"\n```\n\nThe easiest way to run tests is using Docker:\n\n```bash\n# Run all tests\ndocker compose run --rm epp_proxy bash -c \"cd /opt/erlang/epp_proxy \u0026\u0026 rebar3 ct\"\n\n# Run a specific test suite\ndocker compose run --rm epp_proxy bash -c \"cd /opt/erlang/epp_proxy \u0026\u0026 rebar3 ct --suite apps/epp_proxy/test/epp_http_client_SUITE\"\n\n# Start a shell for debugging\ndocker compose run --rm epp_proxy bash -c \"cd /opt/erlang/epp_proxy \u0026\u0026 rebar3 shell\"\n\n# Then in the Erlang shell:\napplication:get_all_env(epp_proxy).\n# To exit the shell:\nhalt().\n```\n\nAfter you finish testing, you can stop the process by reading the stored pid:\n\n    $ kill `cat apps/epp_proxy/priv/test_backend_app/pidfile`\n\nTODO\n----\n\n1. Ensure CRL gets updated periodically without a need for restart of the service\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finternetee%2Fepp_proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finternetee%2Fepp_proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finternetee%2Fepp_proxy/lists"}