├── LICENSE ├── README.md └── ssr-decode /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-2021 LuXu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shadowsocks(R)/V2Ray subscription decoder/parser 2 | 3 | A 100-line POSIX compatible shell script to decode, parse Shadowsocks(R)/V2Ray subscription link and create configuration files. 4 | 5 | **Disclaimer:** This is a toy project. I don't know the standard of the encoding of those link URLs, so some parsing could quite possibly go wrong. 6 | 7 | ## Requirement: 8 | 9 | - `base64` to decode base64 format data 10 | - `curl` or `wget` to download http links (optional) 11 | 12 | ## Usage 13 | 14 | The script accepts one or more links as CLI arguments or from pipe. The links can be one of the formats: 15 | - A single `ss://` or `ssr://` or `vmess://` link. This contains a single configuration. 16 | - A `http(s)://` subscription link. This normally contains multiple configurations. 17 | - A base64 encoded string downloaded from a subscription link. 18 | 19 | ``` 20 | ssr-decode [ http(s)://link | ss(r)://BASE64 | vmess://BASE64 | BASE64 | < input.txt ] 21 | ``` 22 | 23 | ### Issues 24 | 25 | Some links encode the strings in other encodings other than UTF-8, the script will still decode with UTF-8. So, expect some non-sense garbles if you run into some of them. 26 | 27 | ### Customization 28 | 29 | The `local_port` and `timeout` in the shadowsocks settings can be controlled with environment variables by `LOCAL_PORT` and `TIMEOUT`, the default is 1080 for local port and 300 for timeout 30 | 31 | ```sh 32 | LOCAL_PORT=1234 TIMEOUT=600 ssr-decode 33 | ``` 34 | 35 | ## Output 36 | 37 | The script will generate `*.json` configuration files for each Shadowsocks(R)/V2Ray setup. 38 | 39 | - The ShadowsocksR configuration file will be named `ssr-$group-$remarks.json` with `group` normally being the service provider, `remarks` being the description of this setup. 40 | - The Shadowsocks configuration file will be named `ss-$server-$port.json`. 41 | - The V2Ray configuration file will be named `v2ray-$ps.json` with `ps` normally being the description. 42 | -------------------------------------------------------------------------------- /ssr-decode: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Author: Lu Xu 4 | # License: MIT License. 2020-2021 Lu Xu 5 | # 6 | # A shell script to parse Shadowsocks(R)/v2ray subscription links 7 | # and generate json config files 8 | # 9 | # Requirements: base64, curl/wget (optional) 10 | 11 | local_port=${LOCAL_PORT:-1080} 12 | timeout=${TIMEOUT:-300} 13 | 14 | decode_base64() { 15 | case "$((${#1} % 4))" in 16 | 2) echo "$1==" ;; 17 | 3) echo "$1=" ;; 18 | *) echo "$1" ;; 19 | esac | tr '_-' '/+' | grep -o "^[a-zA-Z0-9+/=]*" | base64 -d 20 | } 21 | 22 | decode_ss() { 23 | IFS=:@\ read -r method password server server_port <<- EOF 24 | ${1%%/?*} 25 | EOF 26 | conf=$(echo "ss-${server:-NoServer}-${server_port:-NoPort}.json" | tr "/ " _) 27 | echo "Saving to $conf" 28 | cat > "$conf" <<- EOF 29 | { 30 | "server": "$server", 31 | "server_port": $server_port, 32 | "password": "$password", 33 | "local_address": "127.0.0.1", 34 | "local_port": $local_port, 35 | "timeout": $timeout, 36 | "method": "$method", 37 | } 38 | EOF 39 | } 40 | 41 | decode_ssr() { 42 | IFS=:\ read -r server server_port protocol method obfs password <<- EOF 43 | ${1%%/?*} 44 | EOF 45 | 46 | while IFS='=' read -r key value; do 47 | [ -n "$value" ] && eval "$key=\"$(decode_base64 "$value")\"" 48 | done <<- EOF 49 | $(echo "${1#*/?}" | tr '&' '\n') 50 | EOF 51 | 52 | conf=$(echo "ssr-${group:-NoGroup}-${remarks:-Null}.json" | tr "/ " _) 53 | echo "Saving to $conf" 54 | cat > "$conf" <<- EOF 55 | { 56 | "server": "$server", 57 | "server_port": $server_port, 58 | "password": "$(decode_base64 "$password")", 59 | "local_address": "127.0.0.1", 60 | "local_port": $local_port, 61 | "timeout": $timeout, 62 | "method": "$method", 63 | "protocol": "$protocol", 64 | "protocol_param": "${protoparam:-null}", 65 | "obfs": "$obfs", 66 | "obfs_param": "${obfsparam:-null}" 67 | } 68 | EOF 69 | } 70 | 71 | decode_vmess() { 72 | while IFS=': ' read -r key value; do 73 | [ -n "$value" ] && eval "$key=\"$value\"" 74 | done <<- EOF 75 | $(echo "$1" | tr '{,}' '\n' | tr -d '"') 76 | EOF 77 | conf=$(echo "v2ray-${add-null}-${ps-null}.json" | tr "/ " _) 78 | echo "Saving to $conf" 79 | echo "$1" > "$conf" 80 | } 81 | 82 | decode_link() { 83 | info=$(decode_base64 "${1#*://}") 84 | case "${1%%:*}" in 85 | ss) decode_ss "$info" ;; 86 | ssr) decode_ssr "$info" ;; 87 | vmess) decode_vmess "$info" ;; 88 | https?) decode_link "$(curl -Ss "$1" || wget -qO - "$1")" ;; 89 | *) for link in $info; do decode_link "$link"; done ;; 90 | esac 91 | } 92 | 93 | if [ "$#" = 1 ] && [ "$1" = "-h" ]; then 94 | echo "Usage: ssr-decode [ (http|https|ss|ssr|vmess):// | BASE64 | < input.txt ]" 95 | elif [ "$#" = 0 ]; then 96 | while read -r link; do 97 | decode_link "$link" 98 | done 99 | else 100 | for link in "$@"; do 101 | decode_link "$link" 102 | done 103 | fi 104 | 105 | # vim: noet 106 | --------------------------------------------------------------------------------