{"id":13775909,"url":"https://github.com/shadowsocks/shadowsocks-restful-api","last_synced_at":"2025-10-19T14:32:21.584Z","repository":{"id":46260037,"uuid":"139014748","full_name":"shadowsocks/shadowsocks-restful-api","owner":"shadowsocks","description":"Secure, reliable, standard restful api for managing shadowsocks-libev","archived":true,"fork":false,"pushed_at":"2023-09-20T00:04:04.000Z","size":88,"stargazers_count":83,"open_issues_count":10,"forks_count":49,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-12-16T23:46:42.485Z","etag":null,"topics":["restful-api","shadowsocks","shadowsocks-libev"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/shadowsocks.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}},"created_at":"2018-06-28T12:24:45.000Z","updated_at":"2024-12-12T11:52:25.000Z","dependencies_parsed_at":"2024-01-07T22:47:38.424Z","dependency_job_id":"28c57f71-3f1a-4124-8956-1f841919bbd5","html_url":"https://github.com/shadowsocks/shadowsocks-restful-api","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadowsocks%2Fshadowsocks-restful-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadowsocks%2Fshadowsocks-restful-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadowsocks%2Fshadowsocks-restful-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shadowsocks%2Fshadowsocks-restful-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shadowsocks","download_url":"https://codeload.github.com/shadowsocks/shadowsocks-restful-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237152833,"owners_count":19263792,"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":["restful-api","shadowsocks","shadowsocks-libev"],"created_at":"2024-08-03T17:01:54.211Z","updated_at":"2025-10-19T14:32:21.252Z","avatar_url":"https://github.com/shadowsocks.png","language":"JavaScript","funding_links":[],"categories":["\u003ca id=\"d03d494700077f6a65092985c06bf8e8\"\u003e\u003c/a\u003e工具"],"sub_categories":["\u003ca id=\"cb16466a31a167bb61f39e2a4a85f449\"\u003e\u003c/a\u003eShadowsocks"],"readme":"# Shadowsocks Restful Api\nA secure, reliable, standard restful api for managing shadowsocks-libev.\n\nA web app that manages users, server, nodes, products, accounts, and traffic can be found from [shadowsocks-hub](https://github.com/shadowsocks/shadowsocks-hub).\n\n## Install with Docker\n\n#### Install Docker and Compose plugin:\n```\ncurl -fsSL https://get.docker.com -o get-docker.sh\nDRY_RUN=1 sudo sh ./get-docker.sh\n```\n\n#### Download shadowsocks-restful-api:\n```\ncd ~\ngit clone https://github.com/shadowsocks/shadowsocks-restful-api.git\n```\n\n#### Change the login password of REST-api:\n```\ncd shadowsocks-restful-api/\nnano .env\n```\n* Note: LOGIN_PASSWORD in .env file, should be long and complex\n\n#### Build and run:\n```\ndocker build -t shadow-rest:1.0.0 .\ndocker compose up -d\n```\n\n#### Test it with LOGIN_PASSWORD to get jwt token:\n```\ncurl -ik -H \"Content-Type: application/json\" -X POST -d '{\"password\":\"changeThisSecret-long-long-pa$$word!@#123!@#\"}' https://\u003cpublic_ip_of_server\u003e:4001/login\n```\nResponse example:  \n```json\n{\"token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1Mjk0ODg0MTcsImV4cCI6MTUyOTU3NDgxN30.9wdDV4hXvHdCkWhcOFpW2YXvSL6WupWSj2kTI6XMhFk\"}\n```\n\n## Install (Ubuntu 16.04)\n\n#### Download shadowsocks-restful-api:\n```\ncd ~\ngit clone https://github.com/shadowsocks/shadowsocks-restful-api.git\n```\n\n#### Install Node:\n```\ncurl -sL https://deb.nodesource.com/setup_8.x | sudo bash -\nsudo apt-get install nodejs -y\n```\n\n#### Install dependencies:\n```\nsudo apt-get install -y python-dev make g++ screen\ncd ~/shadowsocks-restful-api\nnpm i\n```\n\n#### Install shadowsocks-libev:\n```\nsudo apt-get install software-properties-common -y\nsudo add-apt-repository ppa:max-c-lv/shadowsocks-libev -y\nsudo apt-get update\nsudo apt install shadowsocks-libev\n```\n\n#### Create digital certificate:\n```\ncd ~/shadowsocks-restful-api\nopenssl req -nodes -x509 -newkey rsa:4096 -keyout server.key -out server.cert -days 365\n```\n\n#### Create config file:\n```\ncd ~/shadowsocks-restful-api\ntouch .env\necho 'LOGIN_PASSWORD = pleaseChangeThisPassword' \u003e\u003e .env\necho 'LISTEN_PORT = 4001' \u003e\u003e .env\n```\n\n## Run\n\n#### Run shadowsocks-libev in the background:\n```\nscreen -dm ss-manager -u --manager-address /tmp/shadowsocks-manager.sock --fast-open\n```\n\n#### Run shadowsocks-restful-api in the background:\n```\ncd ~/shadowsocks-restful-api\nscreen -dm node app.js\n```\n\n## API\n\n#### Login\n|                               |                                                                   |\n| :---------------------------- | :---------------------------------------------------------------- |\n| Request method:               |  POST                                                             |\n| Request URL:                  |  https://host_name:port/login                                     |\n| Request Header:               |  Content-Type: application/json                                   |\n| Request Body:                 |  {\"password\": \"your_login_password\"}                              |\n| Response HTTP Status Code:    |  201 Created                                                      |\n| Response Body:                |  {\"token\",\"your_authentication_token\"}                            |\n| Response Error Status Code:   |  401 Unauthorized \u003cbr\u003e 500 Internal Server Error                  |\n\nRequest example (curl):  \n```\ncurl -ik -H \"Content-Type: application/json\" -X POST -d '{\"password\":\"pleaseChangeThisPassword\"}' https://localhost:4001/login\n```\nResponse example:  \n```json\n{\"token\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1Mjk0ODg0MTcsImV4cCI6MTUyOTU3NDgxN30.9wdDV4hXvHdCkWhcOFpW2YXvSL6WupWSj2kTI6XMhFk\"}\n```\n\n#### Ping\n|                               |                                                                   |\n| :---------------------------- | :---------------------------------------------------------------- |\n| Request method:               |  GET                                                              |\n| Request URL:                  |  https://host_name:port/ping                                      |\n| Request Header:               |  Authorization: Bearer your_authentication_toke                   |\n| Response HTTP Status Code:    |  200 OK                                                           |\n| Response Body:                |  {\"pong\":\"pong\"}                                                  |\n| Response Error Status Code:   |  401 Unauthorized \u003cbr\u003e424 (shadowsocks unreachable) \u003cbr\u003e 425 (shadowsocks no response) \u003cbr\u003e 500 Internal Server Error |\n\nRequest example (curl):  \n```\ncurl -ik -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1Mjk0ODg0MTcsImV4cCI6MTUyOTU3NDgxN30.9wdDV4hXvHdCkWhcOFpW2YXvSL6WupWSj2kTI6XMhFk\" https://localhost:4001/ping\n```\nResponse example:  \n```json\n{\"pong\":\"pong\"}\n```\n\n#### Add a port\n|                               |                                                                   |\n| :---------------------------- | :---------------------------------------------------------------- |\n| Request method:               |  POST                                                             |\n| Request URL:                  |  https://host_name:port/                                          |\n| Request Header:               |  Content-Type: application/json \u003cbr\u003e Authorization: Bearer your_authentication_toke |\n| Request Body:                 |  {\"port\": port_number, \"password\": \"port_password\", \"method\": \"encryption_method\"}                |\n| Response HTTP Status Code:    |  201 Created                                                      |\n| Response Error Status Code:   |  401 Unauthorized \u003cbr\u003e 409 (port already exists from shadowsocks) \u003cbr\u003e 410 (port not available from operating system) \u003cbr\u003e 422 (shadowsocks failed adding port) \u003cbr\u003e 427 (operating system failed adding port) 424 (shadowsocks unreachable) \u003cbr\u003e 425 (shadowsocks no response) \u003cbr\u003e 500 Internal Server Error |\n\nRequest example (curl):  \n```\ncurl -ik -H \"Content-Type: application/json\" -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1Mjk0ODg0MTcsImV4cCI6MTUyOTU3NDgxN30.9wdDV4hXvHdCkWhcOFpW2YXvSL6WupWSj2kTI6XMhFk\" -X POST -d '{\"port\": 50000,\"password\":\"2owkq9wu2elwst7\",\"method\":\"chacha20-ietf-poly1305\"}' https://localhost:4001/\n```\n\nSupported encryption methods are: \n  * `aes-128-gcm`\n  * `aes-192-gcm`\n  * `aes-256-gcm`\n  * `aes-128-cfb`\n  * `aes-192-cfb`\n  * `aes-256-cfb`\n  * `aes-128-ctr`\n  * `aes-192-ctr`\n  * `aes-256-ctr`\n  * `camellia-128-cfb`\n  * `camellia-192-cfb`\n  * `camellia-256-cfb`\n  * `bf-cfb`\n  * `chacha20-ietf-poly1305`\n  * `xchacha20-ietf-poly1305`\n  * `salsa20`\n  * `chacha20`\n  * `chacha20-ietf`\n\n  If the `method` field is not supplied, the default method is `aes-256-cfb`.\n\n#### Delete a port\n|                               |                                                                   |\n| :---------------------------- | :---------------------------------------------------------------- |\n| Request method:               |  DELETE                                                           |\n| Request URL:                  |  https://host_name:port?port=port_number                          |\n| Request Header:               |  Authorization: Bearer your_authentication_toke                   |\n| Response HTTP Status Code:    |  204 No Content                                                   |\n| Response Error Status Code:   |  401 Unauthorized \u003cbr\u003e 422 (shadowsocks failed removing port) \u003cbr\u003e 427 (operating system failed removing port) \u003cbr\u003e 424 (shadowsocks unreachable) \u003cbr\u003e 425 (shadowsocks no response) \u003cbr\u003e 500 Internal Server Error |\n\nRequest example (curl):  \n```\ncurl -ik -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1Mjk0ODg0MTcsImV4cCI6MTUyOTU3NDgxN30.9wdDV4hXvHdCkWhcOFpW2YXvSL6WupWSj2kTI6XMhFk\" -X DELETE https://localhost:4001?port=50000\n```\n\n#### Get all ports\n|                               |                                                                   |\n| :---------------------------- | :---------------------------------------------------------------- |\n| Request method:               |  GET                                                              |\n| Request URL:                  |  https://host_name:port/all                                       |\n| Request Header:               |  Authorization: Bearer your_authentication_toke                   |\n| Response HTTP Status Code:    |  200 OK                                                           |\n| Response Body:                |  [{\"port\":port_number, \"password\":\"port_password\",\"method\":\"encryption_method\"}, ... ]         |\n| Response Error Status Code:   |  401 Unauthorized \u003cbr\u003e424 (shadowsocks unreachable) \u003cbr\u003e 425 (shadowsocks no response) \u003cbr\u003e 500 Internal Server Error |\n\nRequest example (curl):  \n```\ncurl -ik -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1Mjk0ODg0MTcsImV4cCI6MTUyOTU3NDgxN30.9wdDV4hXvHdCkWhcOFpW2YXvSL6WupWSj2kTI6XMhFk\" https://localhost:4001/all\n```\nResponse example:  \n```json\n[{\"port\": 50000,\"password\":\"2owkq9wu2elwst7\",\"method\":\"chacha20-ietf-poly1305\"}, {\"port\": 50001,\"password\":\"dowl3829j3suniw6\",\"method\":\"aes-256-cfb\"}]\n```\n\n#### Get traffic for all ports\n|                               |                                                                   |\n| :---------------------------- | :---------------------------------------------------------------- |\n| Request method:               |  GET                                                              |\n| Request URL:                  |  https://host_name:port/traffic/all                               |\n| Request Header:               |  Authorization: Bearer your_authentication_toke                   |\n| Response HTTP Status Code:    |  200 OK                                                           |\n| Response Body:                |  [{\"port\":port_number, \"traffic\": traffic_usage}, ... ]           |\n| Response Error Status Code:   |  401 Unauthorized \u003cbr\u003e424 (shadowsocks unreachable) \u003cbr\u003e 425 (shadowsocks no response) \u003cbr\u003e 500 Internal Server Error |\n\nRequest example (curl):  \n```\ncurl -ik -H \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1Mjk0ODg0MTcsImV4cCI6MTUyOTU3NDgxN30.9wdDV4hXvHdCkWhcOFpW2YXvSL6WupWSj2kTI6XMhFk\" https://localhost:4001/traffic/all\n```\nResponse example:  \n```json\n[{\"port\": 50000,\"traffic\":928727287}, {\"port\": 50001,\"traffic\":0}]\n```\n\n## Authentication\n\nAll the api requests except for login require an Authorization header. The header pattern is: `Authorization: Bearer \u003ctoken\u003e`. The token can be obtained from the login api.\n\nA token expires in 24 hours. A new token is needed once the old one expires. Tokens can be re-used in multiple requests before exiration.\n\n## Security\n\nThis program encrypts all the traffic end-to-end using https. It requires you to set up a digital certificate. There are many ways that you can get a free digital certificate. You may also generate your own self-signed digital certificate:\n\n```\ncd ~/shadowsocks-restful-api/\nopenssl req -nodes -x509 -newkey rsa:4096 -keyout server.key -out server.cert -days 365\n```\n\n## Reliability\n\nThis program aims to achieve best reliability. It will attempt to re-open the ports upon restart of shadowsocks or this program itself. It also keeps monitoring the opened ports. Should anyone were dropped (due to any unprecedented reason), this program would attemp to re-open it.\n\n## Bug report and feature request\n\nWelcome to create an issue for them. Bugs have high priority to get addressed. Feature requests will depend on their popularity, importance.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshadowsocks%2Fshadowsocks-restful-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshadowsocks%2Fshadowsocks-restful-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshadowsocks%2Fshadowsocks-restful-api/lists"}