├── LICENSE ├── README.md ├── config.json ├── core ├── config │ └── config.go ├── encryption │ └── encryption.go ├── environment │ └── environment.go ├── interpreter │ └── interpreter.go ├── log │ └── log.go ├── obfuscation │ └── obfuscation.go ├── relay │ └── relay.go ├── session │ └── session.go ├── shell │ └── shell.go ├── transport │ └── transport.go └── ui │ └── ui.go ├── main.go ├── modules ├── interpreters │ ├── android │ │ └── raw.go │ ├── ios │ │ └── raw.go │ ├── linux │ │ └── raw.go │ ├── macos │ │ └── raw.go │ └── windows │ │ └── raw.go ├── plugins │ └── .gitkeep ├── relays │ ├── go │ │ ├── android │ │ │ └── raw.go │ │ ├── compat │ │ │ └── raw.go │ │ ├── ios │ │ │ └── raw.go │ │ ├── linux │ │ │ └── raw.go │ │ ├── macos │ │ │ └── raw.go │ │ └── windows │ │ │ └── raw.go │ └── php │ │ ├── debug.php │ │ └── raw.php └── stagers │ ├── android │ └── .gitkeep │ ├── ios │ └── .gitkeep │ ├── macos │ └── .gitkeep │ └── windows │ └── .gitkeep └── ui ├── assets ├── audio │ └── bell.mp3 ├── css │ ├── animations-terminal.css │ ├── colors.css │ ├── fonts.css │ ├── index.css │ ├── mediaplayer.css │ ├── menu.css │ ├── shadow.css │ └── terminal.css ├── fonts │ ├── Consolas.ttf │ ├── OpenSans-Bold.ttf │ ├── OpenSans-BoldItalic.ttf │ ├── OpenSans-ExtraBold.ttf │ ├── OpenSans-ExtraBoldItalic.ttf │ ├── OpenSans-Italic.ttf │ ├── OpenSans-Light.ttf │ ├── OpenSans-LightItalic.ttf │ ├── OpenSans-Regular.ttf │ ├── OpenSans-Semibold.ttf │ └── OpenSans-SemiboldItalic.ttf ├── images │ ├── appearance.svg │ ├── back.svg │ ├── books.svg │ ├── box.svg │ ├── brand_acer.svg │ ├── brand_thinkpad.svg │ ├── cards.svg │ ├── chip.svg │ ├── clear.svg │ ├── close.svg │ ├── controls.svg │ ├── expresser-logo.svg │ ├── expresser.svg │ ├── eye.svg │ ├── favicon.png │ ├── fetch.svg │ ├── fingerprint.svg │ ├── home.svg │ ├── io.svg │ ├── javascript.svg │ ├── key.svg │ ├── laptop.svg │ ├── laptop2.svg │ ├── laptop3.svg │ ├── link-unsafe.svg │ ├── link.svg │ ├── loader.svg │ ├── loadline.svg │ ├── lock.svg │ ├── mandelbrot.svg │ ├── message-corner.svg │ ├── newwindow.svg │ ├── os_android.svg │ ├── os_apple.svg │ ├── os_linux.svg │ ├── os_windows.svg │ ├── padlock.svg │ ├── pause.svg │ ├── phone.svg │ ├── phone2.svg │ ├── phone2.svg.2018_11_12_15_16_54.0.svg │ ├── plug.svg │ ├── plus.svg │ ├── proxy-icon.svg │ ├── proxy.svg │ ├── quit.svg │ ├── relay.svg │ ├── relaysbg.svg │ ├── route.svg │ ├── router.svg │ ├── script.svg │ ├── selectall.svg │ ├── server.svg │ ├── session.svg │ ├── settings.svg │ ├── snapmon.svg │ ├── stop.svg │ ├── streammic.svg │ ├── streammon.svg │ ├── tablet.svg │ ├── toggle.svg │ ├── tor.png │ ├── tplink.svg │ ├── tplink_black.svg │ ├── tplink_white.svg │ ├── unknown.svg │ ├── wand.svg │ └── whirl.svg └── js │ ├── http.js │ ├── index.js │ ├── index │ ├── environment.js │ ├── events.js │ ├── functions.js │ └── sockets.js │ ├── mediaplayer.js │ ├── mediaplayer │ └── .gitkeep │ ├── menu.js │ ├── popup.js │ ├── terminal.js │ └── terminal │ ├── commands.js │ ├── environment.js │ ├── events.js │ └── functions.js ├── console_log.html ├── help.html ├── index.html ├── mediaplayer.html └── terminal.html /README.md: -------------------------------------------------------------------------------- 1 |

2 | :warning: Work in progress, do not use. 3 |

4 | 5 |
6 | 7 |

8 | 12 |

13 | 14 |
15 | 16 |

17 | 18 | 19 | 20 |

21 | 22 |

23 | 24 | 25 | 26 |

27 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "connections": { 3 | "127.0.0.1": { 4 | "active": "07-02-2018 11:14:12", 5 | "user-agents": [] 6 | } 7 | }, 8 | "console_height": "137", 9 | "idle_timeout": "600", 10 | "open_browser": false, 11 | "scroll_on_output": true 12 | } 13 | -------------------------------------------------------------------------------- /core/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | /* 4 | 5 | Handles JSON configuration files. 6 | 7 | */ 8 | 9 | import ( 10 | "io/ioutil" 11 | "encoding/json" 12 | 13 | "github.com/buffermet/sewers/core/log" 14 | ) 15 | 16 | func Configure(json_path string, new_json_data map[string][]string) { 17 | // Read old config 18 | json_encoded, e := ioutil.ReadFile(json_path) 19 | if e != nil { 20 | log.Fatal(e.Error()) 21 | } 22 | 23 | // Encode old config 24 | var json_decoded map[string]interface{} 25 | if e := json.Unmarshal([]byte(json_encoded), &json_decoded); e != nil { 26 | log.Error("invalid JSON file: " + log.BOLD + json_path + log.RESET + "\n[" + log.BOLD_RED + "STACK TRACE" + log.RESET + "]" + "\n" + e.Error()) 27 | } 28 | 29 | // Set new config 30 | for param, value := range new_json_data { 31 | json_decoded[param] = value[0] 32 | } 33 | 34 | // Indent config 35 | json_indented, e := json.MarshalIndent(json_decoded, "", "\t") 36 | if e != nil { 37 | log.Error("could not indent JSON data.\n[" + log.BOLD_RED + "STACK TRACE" + log.RESET + "]" + "\n" + e.Error()) 38 | } 39 | 40 | // Write new config 41 | ioutil.WriteFile(json_path, json_indented, 0600) 42 | } 43 | -------------------------------------------------------------------------------- /core/encryption/encryption.go: -------------------------------------------------------------------------------- 1 | package encryption 2 | 3 | /* 4 | 5 | Handles encryption protocol. 6 | 7 | */ 8 | 9 | import ( 10 | "crypto/aes" 11 | "crypto/cipher" 12 | "crypto/rand" 13 | "encoding/base64" 14 | "errors" 15 | "io" 16 | "log" 17 | ) 18 | 19 | func NewKey() []byte { 20 | return []byte("") 21 | } 22 | 23 | func Encrypt(key, payload []byte) ([]byte, error) { 24 | blockcipher, err := aes.NewCipher(key) 25 | if err != nil { 26 | return nil, err 27 | } 28 | 29 | encoded_payload := base64.StdEncoding.EncodeToString(payload) 30 | ciphertext := make([]byte, aes.BlockSize + len(encoded_payload)) 31 | 32 | iv := ciphertext[:aes.BlockSize] 33 | if _, err := io.ReadFull(rand.Reader, iv); err != nil { 34 | return nil, err 35 | } 36 | 37 | cfb := cipher.NewCFBEncrypter(blockcipher, iv) 38 | cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(encoded_payload)) 39 | 40 | return []byte(base64.StdEncoding.EncodeToString(ciphertext)), nil 41 | } 42 | 43 | func Decrypt(key, payload []byte) ([]byte, error) { 44 | blockcipher, err := aes.NewCipher(key) 45 | if err != nil { 46 | return nil, err 47 | } 48 | 49 | payload, err = base64.StdEncoding.DecodeString(string(payload)) 50 | if err != nil { 51 | log.Fatal(err) 52 | } 53 | 54 | if len(payload) < aes.BlockSize { 55 | return nil, errors.New("ciphertext too short") 56 | } 57 | 58 | iv := payload[:aes.BlockSize] 59 | payload = payload[aes.BlockSize:] 60 | 61 | cfb := cipher.NewCFBDecrypter(blockcipher, iv) 62 | cfb.XORKeyStream(payload, payload) 63 | 64 | return payload, nil 65 | } 66 | -------------------------------------------------------------------------------- /core/environment/environment.go: -------------------------------------------------------------------------------- 1 | package environment 2 | 3 | /* 4 | 5 | Handles installed environment. 6 | 7 | */ 8 | 9 | import ( 10 | "fmt" 11 | "os" 12 | "regexp" 13 | 14 | "github.com/buffermet/sewers/core/shell" 15 | ) 16 | 17 | var ( 18 | PATH_GO string 19 | PATH_RELAYS string 20 | PATH_MODULES_RELAYS string 21 | PATH_MODULES_STAGERS string 22 | PATH_MODULES_INTERPRETERS string 23 | PATH_MODULES_PLUGINS string 24 | PATH_SEWERS = "/src/github.com/buffermet/sewers" 25 | PATH_UI string 26 | VERSION = "1.0" 27 | WHOAMI string 28 | ) 29 | 30 | func goPath() string { 31 | go_path := os.Getenv("GOPATH") 32 | if go_path == "" { 33 | stdout_bytes, err := shell.Output("go env") 34 | if err != nil { 35 | fmt.Println("error: could not determine GOPATH: " + err.Error()) 36 | os.Exit(1) 37 | } 38 | stdout_bytes = regexp.MustCompile(`(?s).*GOPATH="([^"]+)".*`).ReplaceAll(stdout_bytes, []byte("${1}")) 39 | if len(stdout_bytes) == 0 { 40 | fmt.Println("error: could not find GOPATH of go environment") 41 | os.Exit(1) 42 | } 43 | return string(stdout_bytes) 44 | } 45 | return go_path 46 | } 47 | 48 | func whoAmI() string { 49 | user, _ := shell.Output("whoami") 50 | hostname, _ := shell.Output("hostname") 51 | regexp_whitespace := regexp.MustCompile(`(?s)\s`) 52 | user = regexp_whitespace.ReplaceAll(user, []byte("")) 53 | hostname = regexp_whitespace.ReplaceAll(hostname, []byte("")) 54 | return string(user) + "@" + string(hostname) 55 | } 56 | 57 | func Init() { 58 | PATH_GO = goPath() 59 | PATH_UI = PATH_GO + PATH_SEWERS + "/ui" 60 | PATH_RELAYS = PATH_GO + PATH_SEWERS + "/relays" 61 | PATH_MODULES_RELAYS = PATH_GO + PATH_SEWERS + "/modules/relays" 62 | PATH_MODULES_STAGERS = PATH_GO + PATH_SEWERS + "/modules/stagers" 63 | PATH_MODULES_INTERPRETERS = PATH_GO + PATH_SEWERS + "/modules/interpreters" 64 | PATH_MODULES_PLUGINS = PATH_GO + PATH_SEWERS + "/modules/plugins" 65 | WHOAMI = whoAmI() 66 | } 67 | -------------------------------------------------------------------------------- /core/interpreter/interpreter.go: -------------------------------------------------------------------------------- 1 | package interpreter 2 | 3 | /* 4 | 5 | Raw interpreter handlers. 6 | 7 | */ 8 | 9 | import ( 10 | "errors" 11 | "io/ioutil" 12 | "regexp" 13 | 14 | "github.com/buffermet/sewers/core/environment" 15 | ) 16 | 17 | type Interpreter struct { 18 | Device string 19 | EncryptionKey []byte 20 | FetchRate []int 21 | FetchRateTag string 22 | Hostname string 23 | Icon string 24 | InterpreterGetTag string 25 | InterpreterPostTag string 26 | InterpreterStreamTag string 27 | Logo string 28 | OS string 29 | Payload []byte 30 | RelayAddress string 31 | SessionID string 32 | SewersGetTag string 33 | SewersPostTag string 34 | SewersStreamTag string 35 | StreamRate []int 36 | StreamTag string 37 | TerminalSize []int 38 | UserAgent string 39 | } 40 | 41 | func New(platform string) (*[]byte, error) { 42 | if "" != regexp.MustCompile(`^(android|ios|linux|macos|windows)$`).FindString(platform) { 43 | return nil, errors.New("tried to generate payload for invalid platform: " + platform) 44 | } 45 | payload_path := environment.PATH_MODULES_INTERPRETERS + "/" + platform + "/raw.go" 46 | payload, err := ioutil.ReadFile(payload_path) 47 | if err != nil { 48 | return nil, errors.New(err.Error()) 49 | } 50 | return &payload, nil 51 | } 52 | -------------------------------------------------------------------------------- /core/log/log.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | /* 4 | 5 | Handles StdOut and HTML console output. 6 | 7 | */ 8 | 9 | import ( 10 | "fmt" 11 | "io/ioutil" 12 | "os" 13 | "strings" 14 | "time" 15 | 16 | "github.com/buffermet/sewers/core/environment" 17 | ) 18 | 19 | const ( 20 | BLACK_ON_YELLOW = "\x1b[30;43m" 21 | BOLD = "\x1b[1m" 22 | BOLD_BLACK_ON_GREY = "\x1b[1;7;30m" 23 | BOLD_BLUE = "\x1b[1;34m" 24 | BOLD_GREEN = "\x1b[1;32m" 25 | BOLD_GREY = "\x1b[1;30m" 26 | BOLD_RED = "\x1b[1;31m" 27 | BOLD_YELLOW = "\x1b[1;33m" 28 | ON_GREEN = "\x1b[30;42m" 29 | ON_YELLOW = "\x1b[30;43m" 30 | RESET = "\x1b[0m" 31 | WHITE_ON_RED = "\x1b[1;41m" 32 | HTML_BLACK_ON_YELLOW = "" 33 | HTML_BOLD = "" 34 | HTML_BOLD_BLACK_ON_GREY = "" 35 | HTML_BOLD_BLUE = "" 36 | HTML_BOLD_GREEN = "" 37 | HTML_BOLD_GREY = "" 38 | HTML_BOLD_RED = "" 39 | HTML_BOLD_YELLOW = "" 40 | HTML_ON_GREEN = "" 41 | HTML_ON_YELLOW = "" 42 | HTML_RESET = "" 43 | HTML_WHITE_ON_RED = "" 44 | ) 45 | 46 | func Timestamp() string { 47 | return string(time.Now().Format("02-01-2006 15:04:05")) 48 | } 49 | 50 | func Info(message string) { 51 | timestamp := BOLD_GREY + Timestamp() + RESET + " " 52 | fmt.Println(timestamp + message) 53 | logToConsole(timestamp + message) 54 | } 55 | 56 | func Warn(message string) { 57 | timestamp := BOLD_GREY + Timestamp() + RESET + " " 58 | fmt.Println(timestamp + BLACK_ON_YELLOW + "WARNING" + RESET + " " + message) 59 | logToConsole(timestamp + BLACK_ON_YELLOW + "WARNING" + RESET + " " + message) 60 | } 61 | 62 | func Error(message string) { 63 | timestamp := BOLD_GREY + Timestamp() + RESET + " " 64 | fmt.Println(timestamp + BOLD_RED + "ERROR" + RESET + " " + message) 65 | logToConsole(timestamp + BOLD_RED + "ERROR" + RESET + " " + message) 66 | } 67 | 68 | func Fatal(message string) { 69 | fmt.Println(WHITE_ON_RED + "!!!" + RESET + " " + message) 70 | logToConsole(WHITE_ON_RED + "!!!" + RESET + " " + message) 71 | os.Exit(1) 72 | } 73 | 74 | func Raw(message string) { 75 | fmt.Println(message) 76 | logToConsole(message) 77 | } 78 | 79 | func logToConsole(message string) { 80 | html_string := strings.Replace(message, " ", " ", -1) 81 | html_string = strings.Replace(html_string, RESET, HTML_RESET, -1) 82 | html_string = strings.Replace(html_string, BOLD, HTML_BOLD, -1) 83 | html_string = strings.Replace(html_string, ON_GREEN, HTML_ON_GREEN, -1) 84 | html_string = strings.Replace(html_string, ON_YELLOW, HTML_ON_YELLOW, -1) 85 | html_string = strings.Replace(html_string, WHITE_ON_RED, HTML_WHITE_ON_RED, -1) 86 | html_string = strings.Replace(html_string, BLACK_ON_YELLOW, HTML_BLACK_ON_YELLOW, -1) 87 | html_string = strings.Replace(html_string, BOLD_GREY, HTML_BOLD_GREY, -1) 88 | html_string = strings.Replace(html_string, BOLD_RED, HTML_BOLD_RED, -1) 89 | html_string = strings.Replace(html_string, BOLD_GREEN, HTML_BOLD_GREEN, -1) 90 | html_string = strings.Replace(html_string, BOLD_BLUE, HTML_BOLD_BLUE, -1) 91 | html_string = strings.Replace(html_string, BOLD_YELLOW, HTML_BOLD_YELLOW, -1) 92 | html_string = strings.Replace(html_string, BOLD_BLACK_ON_GREY, HTML_BOLD_BLACK_ON_GREY, -1) 93 | html_string += "\n" 94 | 95 | logfile, err := os.OpenFile( 96 | environment.PATH_UI + "/console_log.html", 97 | os.O_APPEND | os.O_WRONLY, 98 | 0600) 99 | if err != nil { 100 | fmt.Println(err.Error()) 101 | } 102 | 103 | defer logfile.Close() 104 | 105 | if _, err = logfile.WriteString(html_string); err != nil { 106 | fmt.Println(err.Error()) 107 | } 108 | } 109 | 110 | func ClearConsole(ip string) { 111 | err := ioutil.WriteFile( 112 | environment.PATH_UI + "/console_log.html", 113 | []byte(""), 114 | 0600) 115 | if err != nil { 116 | fmt.Println(err.Error()) 117 | } 118 | Info(ip + " cleared the console log") 119 | } 120 | -------------------------------------------------------------------------------- /core/obfuscation/obfuscation.go: -------------------------------------------------------------------------------- 1 | package obfuscation 2 | 3 | /* 4 | 5 | Handles payload obfuscation. 6 | 7 | */ 8 | 9 | import ( 10 | // "errors" 11 | "math/rand" 12 | "regexp" 13 | // "strconv" 14 | "time" 15 | ) 16 | 17 | type CodeSet struct { 18 | AfterSets []int 19 | BeforeSets []int 20 | ChildSets []int 21 | ID int 22 | Imports []string 23 | ParentSet int 24 | Variants []string 25 | } 26 | 27 | var ( 28 | CodeSetInterpreterAndroid []CodeSet 29 | CodeSetInterpreterIOS []CodeSet 30 | CodeSetInterpreterLinux []CodeSet 31 | CodeSetInterpreterMacOS []CodeSet 32 | CodeSetInterpreterWindows []CodeSet 33 | CodeSetRelayPhp []CodeSet 34 | CodeSetStagerAndroid []CodeSet 35 | CodeSetStagerIOS []CodeSet 36 | CodeSetStagerLinux []CodeSet 37 | CodeSetStagerMacOS []CodeSet 38 | CodeSetStagerWindows []CodeSet 39 | ) 40 | 41 | func RandomString(length int) string { 42 | rand.Seed(time.Now().UnixNano()) 43 | 44 | chars := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") 45 | buffer := "" 46 | for i := 0; i < length; i++ { 47 | index := rand.Intn(length) 48 | buffer += string(chars[index]) 49 | } 50 | 51 | return buffer 52 | } 53 | 54 | func ObfuscateSource(payload []byte, wordlist []string, shuffle bool) ([]byte, error) { 55 | // Count amount of obfuscatable strings 56 | r := regexp.MustCompile("obf_[a-zA-Z_]*") 57 | obf_matches := r.FindAll(payload, -1) 58 | 59 | count := 0 60 | p := payload 61 | for i := 0; i < len(obf_matches); i++ { 62 | r = regexp.MustCompile(string(obf_matches[i])) 63 | if len(r.FindAll(p, -1)) > 0 { 64 | p = r.ReplaceAll(p, []byte("")) 65 | count += 1 66 | } 67 | } 68 | 69 | // Make sure enough obfuscation strings are provided 70 | if len(wordlist) >= count { 71 | // Shuffle wordlist if shuffling is enabled 72 | if shuffle == true { 73 | // 74 | } 75 | for i := 0; i < len(obf_matches); i++ { 76 | r = regexp.MustCompile(string(obf_matches[i])) 77 | payload = r.ReplaceAll(payload, []byte(wordlist[i])) 78 | } 79 | } 80 | 81 | return payload, nil 82 | } 83 | /* <<<<<<<<<<<<<<< 84 | func getCodeSet(codeSets []*CodeSet, id int) (*CodeSet, error) { 85 | for i := 0; i < len(codeSets); i++ { 86 | this_set := codeSets[i] 87 | if this_set.ID == id { 88 | return this_set, nil 89 | } 90 | } 91 | return nil, errors.New("sets of code did not include set " + strconv.Itoa(id)) 92 | } 93 | 94 | func getMainSets(codeSets []*CodeSet) []int { 95 | var main_sets []int 96 | for i := 0; i < len(codeSets); i++ { 97 | if codeSets[i].ParentSet != -1 { 98 | 99 | } 100 | } 101 | } 102 | 103 | func assemble(codeSets []*CodeSet, order []int, thisSet *CodeSet) string { 104 | index := rand.Intn(len(thisSet.ChildSets) + 1) 105 | child_id := thisSet.ChildSets[index] 106 | child_set, err := getCodeSet(codeSets, child_id) 107 | if err != nil { 108 | if len(child_set.ChildSets) > 0 { 109 | 110 | } 111 | } 112 | } 113 | 114 | // AfterSets []int 115 | // BeforeSets []int 116 | // ChildSets []int 117 | // ID int 118 | // Imports []string 119 | // ParentSet int 120 | // Variants []string 121 | 122 | func ShuffleSource(codeSets []*CodeSet) ([]byte, error) { 123 | var assembled []byte 124 | var imports []string 125 | source_prefix := []byte("package main\n\nimport (\n{{IMPORTS}}\n)\n\n{{ASSEMBLED}}") 126 | 127 | rand.Seed(time.Now().UnixNano()) 128 | this_set := codeSets[a] 129 | 130 | this_source := assemble(codeSets, this_set) 131 | 132 | // return nil, errors.New("code set " + strconv.Itoa(this_set.ID) + " is missing the following nested set of code: " + strconv.Itoa(...)) 133 | 134 | return b, nil 135 | } 136 | 137 | /* 138 | 139 | [] 140 | [] 141 | [] 142 | i 143 | [] 144 | - 145 | [""] 146 | 147 | [2,3,4,5,6,7] 148 | [] 149 | [] 150 | 8 151 | [] 152 | [1] 153 | ["return buffer;"] 154 | 155 | [6] 156 | [8] 157 | [] 158 | 7 159 | [] 160 | [5] 161 | ["buffer += string(chars[index]);"] 162 | 163 | [] 164 | [7,8] 165 | [] 166 | 6 167 | ["math/rand"] 168 | [5] 169 | ["index := rand.Intn(length);","index := int(rand.Float64() * length);","index := int(length * rand.Float64());"] 170 | 171 | [] 172 | [8] 173 | [6,7] 174 | 5 175 | [] 176 | [1] 177 | ["for i := 0; i < length; i++ {\n{{NESTED_CODE}}\n};"] 178 | 179 | [2,3] 180 | [2,3,8] 181 | [] 182 | 4 183 | [] 184 | [1] 185 | ["buffer := \"\";"] 186 | 187 | [2,4] 188 | [2,4,8] 189 | [] 190 | 3 191 | [] 192 | [1] 193 | ["chars := []byte(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\");"] 194 | 195 | [3,4] 196 | [3,4,8] 197 | [] 198 | 2 199 | ["math/rand","time"] 200 | [1] 201 | ["rand.Seed(time.Now().UnixNano());"] 202 | 203 | [0] 204 | [0] 205 | [2,3,4,8] 206 | 1 207 | ["math/rand","time"] 208 | [] 209 | ["func RandomString(length int) string {\n{{NESTED_CODE}}\n};"] 210 | 211 | [1] 212 | [1] 213 | [] 214 | 0 215 | ["errors"] 216 | [] 217 | ["func ShuffleSource(codeSets []CodeSet) ([]byte, error) {\n{{NESTED_CODE}}\n};"] 218 | 219 | */ 220 | -------------------------------------------------------------------------------- /core/relay/relay.go: -------------------------------------------------------------------------------- 1 | package relay 2 | 3 | /* 4 | 5 | Relay config handlers. 6 | 7 | */ 8 | 9 | import ( 10 | "encoding/json" 11 | "errors" 12 | "io/ioutil" 13 | "strings" 14 | 15 | "github.com/buffermet/sewers/core/environment" 16 | "github.com/buffermet/sewers/core/log" 17 | "github.com/buffermet/sewers/core/transport" 18 | ) 19 | 20 | type Relay struct { 21 | InterpreterGetTag string 22 | InterpreterPostTag string 23 | RelayAddress string 24 | RelayID string 25 | SewersGetTag string 26 | SewersPostTag string 27 | Sessions []string 28 | } 29 | 30 | func Get(relay_id string) string { 31 | encoded_json, err := ioutil.ReadFile(environment.PATH_RELAYS + "/" + relay_id + "/" + relay_id + ".json") 32 | if err != nil { 33 | log.Error("could not read relay config " + log.BOLD + environment.PATH_RELAYS + "/" + relay_id + "/" + relay_id + ".json" + log.RESET) 34 | } 35 | 36 | return string(encoded_json) 37 | } 38 | 39 | func GetAddress(relay_id string) (string, error) { 40 | relay_path := environment.PATH_RELAYS + "/" + relay_id + "/" + relay_id + ".json" 41 | encoded, err := ioutil.ReadFile(relay_path) 42 | if err != nil { 43 | return "", errors.New("could not read relay config: " + relay_path) 44 | } 45 | 46 | var decoded map[string]interface{} 47 | err = json.Unmarshal(encoded, &decoded) 48 | if err != nil { 49 | return "", errors.New("could not decode relay config: " + relay_path) 50 | } 51 | 52 | return decoded["relay_address"].(string), nil 53 | } 54 | 55 | func GetAllConfigs() string { 56 | relays := []Relay{} 57 | 58 | // Read relay configs. 59 | var relay_configs []string 60 | config_list, err := ioutil.ReadDir(environment.PATH_RELAYS) 61 | if err != nil { 62 | log.Error(err.Error()) 63 | return "{}" 64 | } 65 | for _, file := range config_list { 66 | relay_configs = append(relay_configs, file.Name()) 67 | } 68 | 69 | // Parse relay data 70 | if len(relay_configs) == 0 { 71 | log.Info("no relays found") 72 | return "{}" 73 | } else { 74 | for i := 0; i < len(relay_configs); i++ { 75 | relay_path := environment.PATH_RELAYS + "/" + relay_configs[i] + "/" + relay_configs[i] + ".json" 76 | json_encoded, err := ioutil.ReadFile(relay_path) 77 | if err != nil { 78 | log.Error(err.Error()) 79 | } 80 | 81 | var json_decoded map[string]interface{} 82 | if err := json.Unmarshal([]byte(json_encoded), &json_decoded); err != nil { 83 | log.Error("invalid JSON file: " + log.BOLD + relay_path + log.RESET + "\n[" + log.BOLD_RED + "STACK TRACE" + log.RESET + "]\n" + err.Error()) 84 | } 85 | 86 | if json_decoded["relay_address"] != nil && json_decoded["sewers_post_tag"] != nil && json_decoded["sewers_get_tag"] != nil { 87 | relay := Relay{} 88 | relay.RelayID = strings.Replace(relay_configs[i], ".json", "", 1) 89 | relay.RelayAddress = json_decoded["relay_address"].(string) 90 | relays = append(relays, relay) 91 | } else { 92 | log.Error(log.BOLD + relay_path + log.RESET + " is missing one of the following parameters: 'relay_address', 'sewers_post_tag' or 'sewers_get_tag'" + "\n[" + log.BOLD_RED + "STACK TRACE" + log.RESET + "]\n" + err.Error()) 93 | } 94 | } 95 | } 96 | 97 | indented, _ := json.MarshalIndent(relays, "", "\t") 98 | 99 | return string(indented) 100 | } 101 | 102 | func FetchSessions(relay string) (string, error) { 103 | json_encoded, err := ioutil.ReadFile(environment.PATH_RELAYS + "/" + relay + "/" + relay + ".json") 104 | if err != nil { 105 | return "", errors.New("cannot read relay config: " + log.BOLD + relay + ".json" + log.RESET + "\n[" + log.BOLD_RED + "STACK TRACE" + log.RESET + "]\n" + err.Error()) 106 | } 107 | 108 | var json_decoded map[string]interface{} 109 | if err := json.Unmarshal([]byte(json_encoded), &json_decoded); err != nil { 110 | log.Error("invalid JSON file: " + log.BOLD + environment.PATH_RELAYS + "/" + relay + "/" + relay + ".json" + log.RESET + "\n[" + log.BOLD_RED + "STACK TRACE" + log.RESET + "]\n" + err.Error()) 111 | } 112 | 113 | sessions := "" 114 | 115 | // Send HTTP request 116 | if json_decoded["relay_address"] != nil && json_decoded["sewers_get_tag"] != nil { 117 | relay_address := json_decoded["relay_address"].(string) 118 | get_tag := json_decoded["sewers_get_tag"].(string) 119 | user_agent := json_decoded["user_agent"].(string) 120 | 121 | response := transport.SendHTTPRequest( 122 | relay_address, 123 | get_tag, 124 | user_agent, 125 | "", 126 | "") 127 | body, err := ioutil.ReadAll(response.Body) 128 | if err != nil { 129 | return "", errors.New("could not read response body (" + err.Error() + ")") 130 | } 131 | defer response.Body.Close() 132 | sessions = string(body) 133 | } else { 134 | return "", errors.New("relay " + log.BOLD + relay + log.RESET + " is missing a \"relay_address\" and/or \"sewers_get_tag\" property.") 135 | } 136 | 137 | return sessions, nil 138 | } 139 | 140 | func New() *Relay { 141 | return &Relay{} 142 | } 143 | 144 | func NewPayload(payload_type string) ([]byte, error) { 145 | payload_path := environment.PATH_RELAYS + "/" + payload_type + "/raw." + payload_type 146 | payload, err := ioutil.ReadFile(environment.PATH_RELAYS + "/" + payload_type + "/raw." + payload_type) 147 | if err != nil { 148 | return []byte(""), errors.New("could not read relay payload, filetype is removed or doesn't exist: " + payload_path) 149 | } 150 | 151 | return payload, nil 152 | } 153 | -------------------------------------------------------------------------------- /core/session/session.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | /* 4 | 5 | Session config handlers. 6 | 7 | */ 8 | 9 | import ( 10 | "errors" 11 | "encoding/json" 12 | "io/ioutil" 13 | 14 | "github.com/buffermet/sewers/core/environment" 15 | ) 16 | 17 | type Session struct { 18 | SessionID string 19 | OS string 20 | Device string 21 | Hostname string 22 | EncryptKey string 23 | RelayAddress string 24 | InterpreterGetTag string 25 | InterpreterPostTag string 26 | SewersGetTag string 27 | SewersPostTag string 28 | FetchRate string 29 | FetchRateTag string 30 | TerminalSize string 31 | FetchSchedule []string 32 | PauseTerminal bool 33 | } 34 | 35 | func Encode(s *Session) (*[]byte, error) { 36 | var encoded map[string]interface{} 37 | encoded["session_id"] = s.SessionID 38 | encoded["os"] = s.OS 39 | encoded["device"] = s.Device 40 | encoded["hostname"] = s.Hostname 41 | encoded["encryption_key"] = s.EncryptKey 42 | encoded["relay_address"] = s.RelayAddress 43 | encoded["interpreter_get_tag"] = s.InterpreterGetTag 44 | encoded["interpreter_post_tag"] = s.InterpreterPostTag 45 | encoded["sewers_get_tag"] = s.SewersGetTag 46 | encoded["sewers_post_tag"] = s.SewersPostTag 47 | encoded["fetch_rate"] = s.FetchRate 48 | encoded["fetch_rate_tag"] = s.FetchRateTag 49 | encoded["terminal_size"] = s.TerminalSize 50 | encoded["fetch_schedule"] = s.FetchSchedule 51 | encoded["pause_terminal"] = s.PauseTerminal 52 | 53 | b, err := json.Marshal(encoded) 54 | if err != nil { 55 | return nil, errors.New("could not JSON encode session config with session ID " + encoded["session_id"].(string)) 56 | } 57 | 58 | return &b, nil 59 | } 60 | 61 | func Get(relay_id, session_id string) (*Session, error) { 62 | encoded, err := GetEncoded(relay_id, session_id) 63 | if err != nil { 64 | return nil, err 65 | } 66 | 67 | s := New() 68 | err = json.Unmarshal(encoded, &s) 69 | if err != nil { 70 | session_path := environment.PATH_RELAYS + "/" + relay_id + "/sessions/" + session_id + ".json" 71 | return nil, errors.New("could not decode JSON file: " + session_path) 72 | } 73 | 74 | return s, nil 75 | } 76 | 77 | func GetEncoded(relay_id, session_id string) ([]byte, error) { 78 | session_path := environment.PATH_RELAYS + "/" + relay_id + "/sessions/" + session_id + ".json" 79 | encoded, e := ioutil.ReadFile(session_path) 80 | if e != nil { 81 | return nil, errors.New("could not read session config: " + session_id) 82 | } 83 | 84 | return encoded, nil 85 | } 86 | 87 | func New() *Session { 88 | return &Session{} 89 | } 90 | 91 | func Set(relay_id, session_id, encoded string) error { 92 | filepath := environment.PATH_RELAYS + "/" + relay_id + "/sessions/" + session_id + ".json" 93 | err := ioutil.WriteFile(environment.PATH_RELAYS + "/" + relay_id + "/sessions/" + session_id + ".json", []byte(encoded), 600) 94 | if err != nil { 95 | return errors.New("could not write file: " + filepath + "\n" + err.Error()) 96 | } 97 | 98 | return nil 99 | } 100 | -------------------------------------------------------------------------------- /core/shell/shell.go: -------------------------------------------------------------------------------- 1 | package shell 2 | 3 | import ( 4 | "os/exec" 5 | "runtime" 6 | ) 7 | 8 | func Output(command string) ([]byte, error) { 9 | var err error 10 | var b []byte 11 | if runtime.GOOS == "android" { 12 | b, err = exec.Command("/system/bin/sh", "-c", command).Output() 13 | } else if runtime.GOOS == "windows" { 14 | b, err = exec.Command("cmd", "/C", command).Output() 15 | } else { 16 | b, err = exec.Command("/usr/bin/env", "sh", "-c", command).Output() 17 | } 18 | return b, err 19 | } -------------------------------------------------------------------------------- /core/transport/transport.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | /* 4 | 5 | Handles HTTP transport. 6 | 7 | */ 8 | 9 | import ( 10 | "net/http" 11 | "strings" 12 | 13 | "github.com/buffermet/sewers/core/log" 14 | ) 15 | 16 | func SendHTTPRequest(relay_address, request_type, user_agent, session_id, payload string) *http.Response { 17 | body := request_type + "\n" + session_id + "\n" + payload 18 | reader := strings.NewReader(body) 19 | 20 | req, err := http.NewRequest( 21 | "POST", 22 | relay_address, 23 | reader) 24 | if err != nil { 25 | log.Error(err.Error()) 26 | } 27 | 28 | if user_agent != "" { 29 | req.Header.Set("User-Agent", user_agent) 30 | } 31 | 32 | client := &http.Client{} 33 | res, err := client.Do(req) 34 | if err != nil { 35 | log.Error(err.Error()) 36 | } 37 | 38 | return res 39 | } 40 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "github.com/buffermet/sewers/core/environment" 5 | "github.com/buffermet/sewers/core/ui" 6 | ) 7 | 8 | func main() { 9 | environment.Init() 10 | ui.Start() 11 | } 12 | -------------------------------------------------------------------------------- /modules/plugins/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/modules/plugins/.gitkeep -------------------------------------------------------------------------------- /modules/relays/go/android/raw.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "ioutil" 5 | "net/http" 6 | ) 7 | 8 | 9 | -------------------------------------------------------------------------------- /modules/relays/go/compat/raw.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io/ioutil" 5 | "net/http" 6 | "time" 7 | ) 8 | 9 | const ( 10 | obf_const_InterpreterGetTag = "obf_tag_interpreter_get_tag" 11 | obf_const_InterpreterPostTag = "obf_tag_interpreter_post_tag" 12 | obf_const_InterpreterStreamTag = "obf_tag_interpreter_stream_tag" 13 | obf_const_Port = "8008" 14 | obf_const_RequestDir = "obf_tag_request_dir" 15 | obf_const_ResponseDir = "obf_tag_response_dir" 16 | obf_const_SewersGetTag = "obf_tag_sewers_get_tag" 17 | obf_const_SewersPostTag = "obf_tag_sewers_get_tag" 18 | obf_const_SewersStreamTag = "obf_tag_sewers_stream_tag" 19 | obf_const_StreamDir = "obf_tag_stream_dir" 20 | ) 21 | 22 | func obf_func_serve(res http.ResponseWriter, req *http.Request) { 23 | defer req.Body.Close() 24 | obf_var_body, _ := ioutil.ReadAll(req.Body) 25 | println(string(obf_var_body)) 26 | } 27 | 28 | func main() { 29 | obf_var_server := &http.Server { 30 | Addr: ":" + obf_const_Port, 31 | Handler: http.HandlerFunc(obf_func_serve), 32 | ReadTimeout: 10 * time.Second, 33 | ReadHeaderTimeout: 10 * time.Second, 34 | WriteTimeout: 5 * time.Second, 35 | } 36 | println(obf_var_server.ListenAndServe().Error()) 37 | } 38 | -------------------------------------------------------------------------------- /modules/relays/go/ios/raw.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "ioutil" 5 | "net/http" 6 | ) 7 | 8 | 9 | -------------------------------------------------------------------------------- /modules/relays/go/linux/raw.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "ioutil" 5 | "net/http" 6 | ) 7 | 8 | 9 | -------------------------------------------------------------------------------- /modules/relays/go/macos/raw.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "ioutil" 5 | "net/http" 6 | ) 7 | 8 | 9 | -------------------------------------------------------------------------------- /modules/relays/go/windows/raw.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "ioutil" 5 | "net/http" 6 | ) 7 | 8 | 9 | -------------------------------------------------------------------------------- /modules/stagers/android/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /modules/stagers/ios/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /modules/stagers/macos/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /modules/stagers/windows/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ui/assets/audio/bell.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/audio/bell.mp3 -------------------------------------------------------------------------------- /ui/assets/css/animations-terminal.css: -------------------------------------------------------------------------------- 1 | @keyframes blinking { 2 | from { 3 | background: red; 4 | } 5 | to { 6 | background: #222; 7 | } 8 | } 9 | @-webkit-keyframes blinking { 10 | from { 11 | background: red; 12 | } 13 | to { 14 | background: #222; 15 | } 16 | } 17 | @keyframes onlineblinking { 18 | from { 19 | background: rgba(100,255,100,.4); 20 | box-shadow: none; 21 | border-color: transparent; 22 | } 23 | to { 24 | background: rgba(0,255,0,1); 25 | box-shadow: 0 0 5px 1px green; 26 | border-color: rgba(0,255,0,.1); 27 | } 28 | } 29 | @-webkit-keyframes onlineblinking { 30 | from { 31 | background: rgba(100,255,100,.4); 32 | box-shadow: none; 33 | border-color: transparent; 34 | } 35 | to { 36 | background: rgba(0,255,0,1); 37 | box-shadow: 0 0 5px 1px green; 38 | border-color: rgba(0,255,0,.1); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ui/assets/css/colors.css: -------------------------------------------------------------------------------- 1 | span.red{ 2 | color: red; 3 | } 4 | span.green{ 5 | color: green; 6 | } 7 | span.lightgreen{ 8 | color: rgb(122, 255, 0); 9 | } 10 | span.blue{ 11 | color: blue; 12 | } 13 | span.cyan{ 14 | color: rgb(0,142,255); 15 | } 16 | span.yellow{ 17 | color: yellow; 18 | } 19 | span.tan, 20 | span.orange{ 21 | color: orange; 22 | } 23 | span.purple{ 24 | color: purple; 25 | } 26 | span.pink{ 27 | color: pink; 28 | } 29 | span.maroon{ 30 | color: maroon; 31 | } 32 | span.grey, 33 | span.gray{ 34 | color: #444; 35 | } 36 | span.black{ 37 | color: #000; 38 | } 39 | span.whitebg{ 40 | background-color: white; 41 | } 42 | span.bold{ 43 | font-weight: bold; 44 | } 45 | span.noshadow{ 46 | text-shadow: none; 47 | } -------------------------------------------------------------------------------- /ui/assets/css/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face{ 2 | font-family: "Consolas"; 3 | src: url("../fonts/Consolas.ttf"); 4 | } 5 | @font-face{ 6 | font-family: "OpenSans-Bold"; 7 | src: url("../fonts/OpenSans-Bold.ttf"); 8 | } 9 | @font-face{ 10 | font-family: "OpenSans-BoldItalic"; 11 | src: url("../fonts/OpenSans-BoldItalic.ttf"); 12 | } 13 | @font-face{ 14 | font-family: "OpenSans-ExtraBold"; 15 | src: url("../fonts/OpenSans-ExtraBold.ttf"); 16 | } 17 | @font-face{ 18 | font-family: "OpenSans-ExtraBoldItalic"; 19 | src: url("../fonts/OpenSans-ExtraBoldItalic.ttf"); 20 | } 21 | @font-face{ 22 | font-family: "OpenSans-Italic"; 23 | src: url("../fonts/OpenSans-Italic.ttf"); 24 | } 25 | @font-face{ 26 | font-family: "OpenSans-Light"; 27 | src: url("../fonts/OpenSans-Light.ttf"); 28 | } 29 | @font-face{ 30 | font-family: "OpenSans-LightItalic"; 31 | src: url("../fonts/OpenSans-LightItalic.ttf"); 32 | } 33 | @font-face{ 34 | font-family: "OpenSans-Regular"; 35 | src: url("../fonts/OpenSans-Regular.ttf"); 36 | } 37 | @font-face{ 38 | font-family: "OpenSans-Semibold"; 39 | src: url("../fonts/OpenSans-Semibold.ttf"); 40 | } 41 | @font-face{ 42 | font-family: "OpenSans-SemiboldItalic"; 43 | src: url("../fonts/OpenSans-SemiboldItalic.ttf"); 44 | } -------------------------------------------------------------------------------- /ui/assets/css/mediaplayer.css: -------------------------------------------------------------------------------- 1 | html, 2 | html body{ 3 | width: 100%; 4 | height: 100%; 5 | margin: 0; 6 | padding: 0; 7 | background: #222; 8 | } 9 | html body div.container{ 10 | position: relative; 11 | height: 100%; 12 | width: 100%; 13 | } 14 | html body div.container audio, 15 | html body div.container video{ 16 | width: 100%; 17 | height: 100%; 18 | margin: 0; 19 | padding: 0; 20 | background-size: 80px auto !important; 21 | background-position: center 50px !important; 22 | background-repeat: no-repeat !important; 23 | } 24 | html body div.container audio{ 25 | background: url(./assets/images/stream-mic.svg); 26 | } 27 | -------------------------------------------------------------------------------- /ui/assets/css/shadow.css: -------------------------------------------------------------------------------- 1 | /* Shadow 1dp */ 2 | .shadow-1dp { 3 | box-shadow: 0 1px 1px 0 rgba(0,0,0,0.14), 0 2px 1px -1px rgba(0,0,0,0.12), 0 1px 3px 0 rgba(0,0,0,0.20); 4 | } 5 | 6 | /* Shadow 2dp */ 7 | .shadow-2dp { 8 | box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.20); 9 | } 10 | 11 | /* Shadow 3dp */ 12 | .shadow-3dp { 13 | box-shadow: 0 3px 4px 0 rgba(0,0,0,0.14), 0 3px 3px -2px rgba(0,0,0,0.12), 0 1px 8px 0 rgba(0,0,0,0.20); 14 | } 15 | 16 | /* Shadow 4dp */ 17 | .shadow-4dp { 18 | box-shadow: 0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.20); 19 | } 20 | 21 | /* Shadow 6dp */ 22 | .shadow-6dp { 23 | box-shadow: 0 6px 10px 0 rgba(0,0,0,0.14), 0 1px 18px 0 rgba(0,0,0,0.12), 0 3px 5px -1px rgba(0,0,0,0.20); 24 | } 25 | 26 | /* Shadw 8dp */ 27 | .shadow-8dp { 28 | box-shadow: 0 8px 10px 1px rgba(0,0,0,0.14), 0 3px 14px 2px rgba(0,0,0,0.12), 0 5px 5px -3px rgba(0,0,0,0.20); 29 | } 30 | 31 | /* Shadow 9dp */ 32 | .shadow-9dp { 33 | box-shadow: 0 9px 12px 1px rgba(0,0,0,0.14), 0 3px 16px 2px rgba(0,0,0,0.12), 0 5px 6px -3px rgba(0,0,0,0.20); 34 | } 35 | 36 | /* Shadow 12dp */ 37 | .shadow-12dp { 38 | box-shadow: 0 12px 17px 2px rgba(0,0,0,0.14), 0 5px 22px 4px rgba(0,0,0,0.12), 0 7px 8px -4px rgba(0,0,0,0.20); 39 | } 40 | 41 | /* Shadow 16dp */ 42 | .shadow-16dp { 43 | box-shadow: 0 16px 24px 2px rgba(0,0,0,0.14), 0 6px 30px 5px rgba(0,0,0,0.12), 0 8px 10px -5px rgba(0,0,0,0.20); 44 | } 45 | 46 | /* Shadow 24dp */ 47 | .shadow-24dp { 48 | box-shadow: 0 24px 38px 3px rgba(0,0,0,0.14), 0 9px 46px 8px rgba(0,0,0,0.12), 0 11px 15px -7px rgba(0,0,0,0.20); 49 | } 50 | -------------------------------------------------------------------------------- /ui/assets/css/terminal.css: -------------------------------------------------------------------------------- 1 | * { 2 | -webkit-appearance: none !important; 3 | -moz-appearance: none !important; 4 | -ms-appearance: none !important; 5 | -o-appearance: none !important; 6 | } 7 | *::selection { 8 | background: white; 9 | color: #000; 10 | text-shadow: none; 11 | } 12 | *::-moz-selection { 13 | background: white; 14 | color: #000; 15 | text-shadow: none; 16 | } 17 | ::-webkit-scrollbar { 18 | display: none; 19 | } 20 | input { 21 | outline: none; 22 | } 23 | html { 24 | background-color: #090A0D; 25 | } 26 | html, 27 | html body { 28 | width: 100%; 29 | height: 100%; 30 | max-width: 100%; 31 | max-height: 100%; 32 | margin: 0; 33 | overflow: hidden; 34 | font-weight: 100; 35 | } 36 | html body div.scrollBox { 37 | position: absolute; 38 | top: 0; 39 | width: 100%; 40 | height: auto; 41 | max-height: calc(100% - 26px - 12px); 42 | overflow-x: hidden; 43 | overflow-y: auto; 44 | } 45 | html body div.scrollBox div.background { 46 | position: fixed; 47 | top: 0; 48 | height: 100%; 49 | width: 100%; 50 | opacity: .1; 51 | background-size: auto 220px; 52 | background-repeat: no-repeat; 53 | background-position: top right; 54 | pointer-events: none; 55 | } 56 | html body div.scrollBox div.terminal { 57 | padding: 29px 3px 3px 3px; 58 | color: #FFF; 59 | font-family: monospace; 60 | font-size: 1em; 61 | text-shadow: 0 -1px 0px rgba(0,0,0,0.333); 62 | word-break: break-all; 63 | user-select: initial; 64 | -webkit-user-select: initial; 65 | -moz-user-select: initial; 66 | -ms-user-select: initial; 67 | -o-user-select: initial; 68 | } 69 | html body div.scrollBox div.terminal a { 70 | color: white; 71 | text-decoration: underline; 72 | cursor: pointer; 73 | user-select: text !important; 74 | -webkit-user-select: text !important; 75 | -moz-user-select: text !important; 76 | -ms-user-select: text !important; 77 | -o-user-select: text !important; 78 | } 79 | html body div.scrollBox div.terminal a:hover { 80 | text-decoration: none; 81 | } 82 | html body div.scrollBox div.terminal img { 83 | max-width: 100%; 84 | vertical-align: baseline; 85 | } 86 | html body div.scrollBox div.terminal img.icon { 87 | display: inline-block; 88 | position: relative; 89 | width: 12px; 90 | height: 12px; 91 | top: 1px; 92 | margin: 0 3px 0 1px; 93 | } 94 | html body div.scrollBox div.terminal img.icon.link { 95 | margin: 0; 96 | } 97 | html body div.scrollBox div.terminal hr { 98 | display: block; 99 | width: calc(100% - 12px); 100 | height: 1px; 101 | background: rgba(255,255,255,0.05); 102 | margin: 6px; 103 | border: none; 104 | padding: 0px; 105 | } 106 | html body form { 107 | position: absolute; 108 | bottom: 0; 109 | width: 100%; 110 | } 111 | html body form div.loadline { 112 | position: absolute; 113 | right: 0; 114 | width: 0%; 115 | height: 1px; 116 | background-color: white; 117 | opacity: 1; 118 | } 119 | html body form div.loadline.stop { 120 | opacity: 0; 121 | width: 100%; 122 | transition: none !important; 123 | -webkit-transition: none !important; 124 | -moz-transition: none !important; 125 | -ms-transition: none !important; 126 | -o-transition: none !important; 127 | } 128 | html body form textarea { 129 | margin: 0; 130 | padding: 0; 131 | outline: none; 132 | width: 100%; 133 | height: calc(100% - 8px); 134 | border: none; 135 | border-top: 1px solid rgba(255,255,255,0.05); 136 | text-shadow: 0 -1px 0px black; 137 | font-size: 1em; 138 | padding: 3px; 139 | background: transparent; 140 | resize: none; 141 | color: #FFF; 142 | } 143 | html body form input[type=button]:hover { 144 | background: rgba(80,80,80,0.4); 145 | } 146 | .displaynone { 147 | display: none; 148 | } 149 | html body preload { 150 | position: absolute; 151 | display: block; 152 | overflow: hidden; 153 | width: 0px; 154 | height: 0px; 155 | } 156 | -------------------------------------------------------------------------------- /ui/assets/fonts/Consolas.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/fonts/Consolas.ttf -------------------------------------------------------------------------------- /ui/assets/fonts/OpenSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/fonts/OpenSans-Bold.ttf -------------------------------------------------------------------------------- /ui/assets/fonts/OpenSans-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/fonts/OpenSans-BoldItalic.ttf -------------------------------------------------------------------------------- /ui/assets/fonts/OpenSans-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/fonts/OpenSans-ExtraBold.ttf -------------------------------------------------------------------------------- /ui/assets/fonts/OpenSans-ExtraBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/fonts/OpenSans-ExtraBoldItalic.ttf -------------------------------------------------------------------------------- /ui/assets/fonts/OpenSans-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/fonts/OpenSans-Italic.ttf -------------------------------------------------------------------------------- /ui/assets/fonts/OpenSans-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/fonts/OpenSans-Light.ttf -------------------------------------------------------------------------------- /ui/assets/fonts/OpenSans-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/fonts/OpenSans-LightItalic.ttf -------------------------------------------------------------------------------- /ui/assets/fonts/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/fonts/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /ui/assets/fonts/OpenSans-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/fonts/OpenSans-Semibold.ttf -------------------------------------------------------------------------------- /ui/assets/fonts/OpenSans-SemiboldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/fonts/OpenSans-SemiboldItalic.ttf -------------------------------------------------------------------------------- /ui/assets/images/appearance.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /ui/assets/images/back.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 37 | 45 | 53 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /ui/assets/images/box.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /ui/assets/images/cards.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 34 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /ui/assets/images/clear.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 31 | 32 | -------------------------------------------------------------------------------- /ui/assets/images/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ui/assets/images/controls.svg: -------------------------------------------------------------------------------- 1 | 2 | image/svg+xml 20 | 23 | 25 | 26 | 27 | 31 | 32 | 35 | 36 | 39 | 40 | 43 | 44 | 47 | 48 | 51 | 52 | 55 | 56 | 59 | 60 | 63 | 64 | 67 | 68 | 71 | 72 | 75 | 76 | 79 | 80 | 83 | 84 | 87 | 88 | 91 | 92 | -------------------------------------------------------------------------------- /ui/assets/images/expresser.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ui/assets/images/eye.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 53 | 59 | 66 | 67 | -------------------------------------------------------------------------------- /ui/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/images/favicon.png -------------------------------------------------------------------------------- /ui/assets/images/fetch.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ui/assets/images/fingerprint.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ui/assets/images/home.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 53 | 59 | 60 | -------------------------------------------------------------------------------- /ui/assets/images/io.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 37 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 54 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /ui/assets/images/javascript.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 61 | 65 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /ui/assets/images/key.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 53 | 58 | 59 | -------------------------------------------------------------------------------- /ui/assets/images/link-unsafe.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 31 | 32 | -------------------------------------------------------------------------------- /ui/assets/images/loader.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 38 | 40 | 43 | 47 | 51 | 52 | 54 | 58 | 62 | 63 | 71 | 80 | 89 | 98 | 107 | 116 | 117 | 119 | 120 | 122 | image/svg+xml 123 | 125 | 126 | 127 | 128 | 129 | 133 | 134 | -------------------------------------------------------------------------------- /ui/assets/images/loadline.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 18 | 22 | 26 | 27 | 36 | 37 | 39 | 40 | 42 | image/svg+xml 43 | 45 | 46 | 47 | 48 | 49 | 52 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /ui/assets/images/lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 31 | 32 | -------------------------------------------------------------------------------- /ui/assets/images/message-corner.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /ui/assets/images/newwindow.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 37 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 54 | 58 | 66 | 74 | 75 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /ui/assets/images/os_apple.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 31 | 32 | -------------------------------------------------------------------------------- /ui/assets/images/os_windows.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 31 | 32 | -------------------------------------------------------------------------------- /ui/assets/images/padlock.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ui/assets/images/pause.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 37 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 55 | 62 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /ui/assets/images/plug.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 22 | 24 | image/svg+xml 25 | 27 | 28 | 29 | 30 | 31 | 33 | 53 | 59 | 60 | -------------------------------------------------------------------------------- /ui/assets/images/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 63 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /ui/assets/images/quit.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 38 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ui/assets/images/route.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 31 | 32 | -------------------------------------------------------------------------------- /ui/assets/images/script.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ui/assets/images/selectall.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 37 | 39 | 40 | 42 | image/svg+xml 43 | 45 | 46 | 47 | 48 | 49 | 51 | 57 | 58 | -------------------------------------------------------------------------------- /ui/assets/images/session.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /ui/assets/images/settings.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ui/assets/images/snapmon.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 31 | 32 | -------------------------------------------------------------------------------- /ui/assets/images/stop.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /ui/assets/images/streammic.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 31 | 32 | -------------------------------------------------------------------------------- /ui/assets/images/streammon.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 16 | 18 | image/svg+xml 19 | 21 | 22 | 23 | 24 | 25 | 27 | 31 | 32 | -------------------------------------------------------------------------------- /ui/assets/images/tablet.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 38 | 40 | 42 | 46 | 50 | 51 | 53 | 57 | 61 | 62 | 64 | 68 | 72 | 73 | 82 | 90 | 98 | 99 | 101 | 102 | 104 | image/svg+xml 105 | 107 | 108 | 109 | 110 | 111 | 114 | 122 | 130 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /ui/assets/images/toggle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /ui/assets/images/tor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/images/tor.png -------------------------------------------------------------------------------- /ui/assets/images/tplink.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ui/assets/images/tplink_black.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ui/assets/images/tplink_white.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ui/assets/images/unknown.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 30 | 34 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /ui/assets/images/wand.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /ui/assets/js/http.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * Sewers UI HTTP package 5 | * 6 | */ 7 | 8 | app.http.Request = async (method, url, headers, body) => { 9 | return new Promise(async(resolve, reject)=>{ 10 | let req = new XMLHttpRequest(); 11 | 12 | try { 13 | req.open(method, url); 14 | 15 | try { 16 | for (let i = 0; i < headers.length; i++) { 17 | const header_name = headers[i][0], 18 | header_value = headers[i][1]; 19 | 20 | req.setRequestHeader(header_name, header_value); 21 | } 22 | } catch(err) { 23 | console.error(err); 24 | } 25 | 26 | req.onreadystatechange = async () => { 27 | if (req.readyState == 4) { 28 | resolve(req); 29 | } 30 | } 31 | } catch(err) { 32 | reject(err); 33 | } 34 | 35 | req.send(body); 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /ui/assets/js/index.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * Sewers UI index package 5 | * 6 | */ 7 | 8 | self.addEventListener("load", async()=>{ 9 | await app.functions.whoAmI(); 10 | await app.functions.getSewersConfig(); 11 | await app.functions.updateCSS(); 12 | await app.functions.showRelays(); 13 | 14 | app.functions.fetchLog(); 15 | setInterval(app.functions.fetchLog, 400); // make websocket 16 | 17 | setInterval(app.functions.cycleNews, 4000); 18 | setTimeout(async()=>{ app.environment.container.classList.remove("hide") }, 720); 19 | }) 20 | -------------------------------------------------------------------------------- /ui/assets/js/index/environment.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * Sewers UI index environment package 5 | * 6 | */ 7 | 8 | // App 9 | const app = {} 10 | 11 | // Modules 12 | app.commands = {} 13 | app.events = {} 14 | app.functions = {} 15 | app.http = {} 16 | app.environment = { 17 | whoami: "", 18 | timezone: "", 19 | lastIP: "", 20 | currentRelay: "", 21 | relayUserAgent: "", 22 | relayConfig: {}, 23 | sewersConfig: {}, 24 | resizingConsole: false, 25 | scrollOnOutput: false, 26 | warnOnRequest: true, 27 | webConsole: document.querySelector("html body div.console"), 28 | consoleContainer: document.querySelector("html body div.console div.consolecontainer"), 29 | consoleClear: document.querySelector("html body div.console div.clear"), 30 | consoleResizeBar: document.querySelector("html body div.console div.resizebar"), 31 | popupBackground: document.querySelector("html body div.popup"), 32 | upstreamIndicator: document.querySelector("html body div.menu div.item div.upstream-indicator"), 33 | backbutton: document.querySelector("html body div.menu div.item[name=backbutton]"), 34 | scrollContainer: document.querySelector("html body div.scrollcontainer"), 35 | container: document.querySelector("html body div.scrollcontainer div.container"), 36 | relayList: document.querySelector("html body div.scrollcontainer div.container div.relaylist"), 37 | relays: document.querySelectorAll("html body div.scrollcontainer div.container div.relaylist div.relay"), 38 | sessions: document.querySelectorAll("html body div.scrollcontainer div.container div.sessionlist div.session"), 39 | newsMessage: document.querySelector("html body div.scrollcontainer div.container div div.header span.newsmessage"), 40 | newsMessageRelays: document.querySelectorAll("html body div.scrollcontainer div.container div.relaylist div.header span.newsmessage"), 41 | newsMessageSessions: document.querySelector("html body div.scrollcontainer div.container div.sessionlist div.header span.newsmessage"), 42 | newsRelays: {}, 43 | newsSessions: {}, 44 | currentRelaysNews: 0, 45 | currentSessionsNews: 0, 46 | } 47 | -------------------------------------------------------------------------------- /ui/assets/js/index/events.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * Sewers UI index events package 5 | * 6 | */ 7 | 8 | // Quit button 9 | /* 10 | document.querySelector("html body div.menu div[name=quit]").addEventListener("click", async()=>{ 11 | // 12 | }); 13 | */ 14 | 15 | // Preferences button 16 | document.querySelector("html body div.menu div.item[name=settings]").addEventListener("click", async()=>{ 17 | app.functions.showPreferences(); 18 | }); 19 | 20 | // Back button 21 | app.environment.backbutton.addEventListener("click", async(event)=>{ 22 | app.environment.backbutton.setAttribute("data-state", "off"); 23 | 24 | app.functions.showRelays(); 25 | }); 26 | 27 | // Console clear button 28 | app.environment.consoleClear.addEventListener("click", async()=>{ 29 | app.http.Request("GET", "/clear_console_log", [[]], "").then(async(res)=>{ 30 | if (res.status == 200) { 31 | app.environment.consoleContainer.innerHTML = ""; 32 | app.functions.fetchLog(); 33 | } 34 | }); 35 | }); 36 | 37 | // Start resizing console with cursor 38 | app.environment.consoleResizeBar.addEventListener("mousedown", async(event)=>{ 39 | app.environment.resizingConsole = true; 40 | }); 41 | 42 | // Start resizing console with touchscreen 43 | app.environment.consoleResizeBar.addEventListener("touchstart", async(event)=>{ 44 | app.environment.resizingConsole = true; 45 | }); 46 | 47 | // Resizing of console with cursor 48 | self.addEventListener("mousemove", async function startResizing(event){ 49 | if (app.environment.resizingConsole) { 50 | app.functions.resizeConsole(event.clientY); 51 | } 52 | }); 53 | 54 | // Resizing of console with touchscreen 55 | self.addEventListener("touchmove", async function resize(event){ 56 | if (app.environment.resizingConsole) { 57 | app.functions.resizeConsole(event.touches[0].clientY); 58 | } 59 | }); 60 | 61 | // Stop resizing console with cursor 62 | self.addEventListener("mouseup", async function stopResizing(event){ 63 | if (app.environment.resizingConsole) { 64 | app.environment.resizingConsole = false; 65 | app.http.Request( "POST", "/config/sewers", [["Content-Type", "application/x-www-form-urlencoded"]], "console_height=" + app.environment.webConsole.getBoundingClientRect().height ); 66 | } 67 | }); 68 | 69 | // Stop resizing console with touchscreen 70 | self.addEventListener("touchend", async function stopResizing(event){ 71 | if (app.environment.resizingConsole) { 72 | app.environment.resizingConsole = false; 73 | app.http.Request( "POST", "/config/sewers", [["Content-Type", "application/x-www-form-urlencoded"]], "console_height=" + app.environment.webConsole.getBoundingClientRect().height ); 74 | } 75 | }); 76 | 77 | // Prevent console from being hidden when resizing window. 78 | self.addEventListener("resize", async()=>{ 79 | if ( app.environment.webConsole.getBoundingClientRect().height >= ( self.innerHeight - 75 ) && app.environment.webConsole.getBoundingClientRect().height > 51 ) { 80 | app.environment.webConsole.style.height = ( self.innerHeight - 75 ) + "px"; 81 | app.environment.consoleResizeBar.style.bottom = ( self.innerHeight - 75 - 1 ) + "px"; 82 | app.environment.scrollContainer.style.height = "calc(100% - " + ( self.innerHeight - 75 ) + "px)"; 83 | 84 | let console_height = app.environment.webConsole.getBoundingClientRect().height; 85 | 86 | app.http.Request("POST", "/config/sewers", [["Content-Type", "application/x-www-form-urlencoded"]], "console_height=" + console_height); 87 | } 88 | }); 89 | -------------------------------------------------------------------------------- /ui/assets/js/index/sockets.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * Sewers UI index websockets package 5 | * 6 | */ 7 | 8 | const socket_address = "ws://" + location.host + "/stream" 9 | -------------------------------------------------------------------------------- /ui/assets/js/mediaplayer.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * Sewers UI mediaplayer package 5 | * 6 | */ 7 | 8 | // Parse URL 9 | const queryLine = window.location.href.replace(/.*\?/g, ""); 10 | const queries = queryLine.split("&"); 11 | const streamType = queries[0], 12 | streamID = queries[1], 13 | streamFile = queries[2]; 14 | 15 | // Define elements 16 | const container = document.querySelector("html body div.container"); 17 | 18 | // Set title 19 | document.title = streamType.toUpperCase() + " " + streamID; 20 | 21 | // Load media 22 | if (streamType == "mic") { 23 | container.append(""); 24 | } else if (streamType == "mon") { 25 | container.append(""); 26 | } else if (streamType == "cam") { 27 | container.append(""); 28 | } else { 29 | container.append("

No stream type specified

"); 30 | } 31 | -------------------------------------------------------------------------------- /ui/assets/js/mediaplayer/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/assets/js/mediaplayer/.gitkeep -------------------------------------------------------------------------------- /ui/assets/js/menu.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * Sewers UI menu package 5 | * 6 | */ 7 | 8 | // Reveal submenus on desktop and mobile 9 | document.querySelectorAll("html body div.menu div.item").forEach(async(item)=>{ 10 | if ( 11 | item.getAttribute("name") !== "xssbutton" 12 | && item.getAttribute("name") !== "backbutton" 13 | ) { 14 | item.addEventListener("mouseenter", async(event)=>{ 15 | event.target.setAttribute("data-state", "on"); 16 | }); 17 | 18 | item.addEventListener("mouseleave", async(event)=>{ 19 | event.target.setAttribute("data-state", "off"); 20 | }); 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /ui/assets/js/popup.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * Sewers UI popup package 5 | * 6 | */ 7 | 8 | app.functions.showPopup = async html => { 9 | app.environment.popupContent.innerHTML = html; 10 | 11 | app.environment.popup.setAttribute("data-state", "on"); 12 | } 13 | 14 | app.functions.closePopup = async () => { 15 | app.environment.popup.setAttribute("data-state", "off"); 16 | 17 | app.environment.popupContent.innerHTML = ""; 18 | } 19 | -------------------------------------------------------------------------------- /ui/assets/js/terminal.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * Sewers UI terminal package 5 | * 6 | */ 7 | 8 | self.addEventListener("load", async()=>{ 9 | app.functions.shrinkInputField().then(async()=>{ 10 | app.functions.resetClearBreaks(); 11 | }); 12 | 13 | await app.functions.getSessionConfig( app.environment.relay, location.pathname.replace(/.*\//, "") ); 14 | await app.functions.getRelayConfig(app.environment.relay); 15 | await app.functions.parseUserAgent(); 16 | 17 | app.functions.printInstructions(); 18 | 19 | Object.keys(app.commands.builtin).forEach(async(command)=>{ 20 | app.commands.builtin[command].load(); 21 | }); 22 | Object.keys(app.commands.pluggedin).forEach(async(command)=>{ 23 | app.commands.pluggedin[command].load(); 24 | }); 25 | 26 | document.title = app.environment.sessionConfig.session_id + ' - ' + app.environment.sessionConfig.hostname; 27 | 28 | app.environment.textarea.focus(); 29 | }); 30 | -------------------------------------------------------------------------------- /ui/assets/js/terminal/environment.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * 4 | * Sewers UI terminal environment package 5 | * 6 | */ 7 | 8 | // App 9 | const app = {}; 10 | 11 | // Modules 12 | app.environment = { 13 | form: document.querySelector("html body form"), 14 | textarea: document.querySelector("html body form textarea"), 15 | scrollBox: document.querySelector("html body div.scrollBox"), 16 | terminal: document.querySelector("html body div.scrollBox div.terminal"), 17 | xssButton: document.querySelector("html body div.menu div.item[name=xssbutton]"), 18 | xssField: document.querySelector("html body div.menu div.item[name=xssbutton] input"), 19 | upstreamIndicator: document.querySelector("html body div.menu div.item div.upstream-indicator"), 20 | ctrlKey: false, 21 | sessionConfig: {}, 22 | relayConfig: {}, 23 | autoFetch: async () => {}, 24 | autoFetchTimeout: null, 25 | fetchDelay: 1000, 26 | autoFetching: false, 27 | loadLine: document.querySelector("html body form div.loadline"), 28 | relay: location.href.replace(/.*\/terminal\//g, "").replace(/\/.*/g, ""), 29 | requestTag: "sewers \xBB ", 30 | responseTag: "interpreter \xBB ", 31 | request: null, 32 | onResponse: async () => {}, 33 | streamingMicrophone: false, 34 | streamingMonitor: false, 35 | streamingShell: false, 36 | streamingWebcam: false, 37 | allowedCharacters: " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz".split(""), 38 | cmdHistory: new Array(), 39 | cmdHistoryIndex: 0, 40 | cmdCurrent: "", 41 | clearBreaks: parseInt( document.querySelector("html body div.scrollBox").getBoundingClientRect().height / 12 ), 42 | micBitrate: "16000", 43 | monBitrate: "512000", 44 | monResolution: "1280x800", 45 | camBitrate: "512000", 46 | camResolution: "1280x800", 47 | fetchOnAutoFetchStart: true, 48 | warnOnReset: false, 49 | scrollOnInput: true, 50 | scrollOnOutput: false, 51 | scrollOnJsInput: false, 52 | playSoundOnStdout: false, 53 | warnOnRequest: true, 54 | warnOnClose: true, 55 | }; 56 | app.http = {}; 57 | app.functions = {}; 58 | app.functions.prototypes = {}; 59 | app.events = {}; 60 | app.commands = {}; 61 | app.commands.prototypes = {}; 62 | app.streams = {}; 63 | app.streams.active = {}; 64 | app.streams.current = ""; 65 | -------------------------------------------------------------------------------- /ui/console_log.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buffermet/sewers/34e61b90919d627fea5129e14c387cb999221879/ui/console_log.html -------------------------------------------------------------------------------- /ui/help.html: -------------------------------------------------------------------------------- 1 |
2 |   Terminal commands 3 |
4 |
5 |     clear                  Clear terminal window with linebreaks. 6 |
7 |     exit                   Exit the terminal (pop-up window only). 8 |
9 |     fetch                  Fetch responses from interpreter. 10 |
11 |     helph,
 ?             Show this menu. 12 |
13 |     telemetry              Show telemetry data of current session. 14 |
15 |     reset                  Reset terminal window. 16 |
17 |     startautofetching      Set automatic fetch rate of this terminal. 18 |
19 |       <MIN SECONDS> <MAX SECONDS> 20 |
21 |     stopautofetching       Stop automatically fetching new packets. 22 |
23 |     xss <CODE>             Execute JavaScript in this terminal. 24 |
25 |
26 |   Sewers commands 27 |
28 |
29 |   Interpreter commands 30 |
31 |
32 | 36 | 38 | 40 | 44 | 46 | 48 | 52 |     shellsh <COMMAND>    Execute shell command. 53 |
54 | 56 | 58 | 62 | 64 | 68 |     fetchrate              Set automatic fetch rate of interpreter. 69 |
70 |       <MIN SECONDS> <MAX SECONDS> 71 |
72 | 74 |
75 |   Module commands 76 |
77 |
-------------------------------------------------------------------------------- /ui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Relays 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 22 | 74 |
75 |
76 |
77 |
78 |
CLEAR
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /ui/mediaplayer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /ui/terminal.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 81 |
82 |
83 |
84 |
85 |
86 |
87 | 88 | 89 |
90 |
91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | --------------------------------------------------------------------------------