├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── SECURITY.md └── app_scripts ├── Caddyfile ├── entrypoint ├── login ├── motd ├── ssh └── server.go ├── telnet ├── web ├── app.css ├── favicon.png ├── index.html └── termynal.css └── wrapper /Dockerfile: -------------------------------------------------------------------------------- 1 | #Build ssh server application 2 | FROM golang:alpine as builder_ssh 3 | 4 | COPY app_scripts/ssh/server.go $GOPATH/src/ 5 | WORKDIR $GOPATH/src/ 6 | 7 | RUN apk add git \ 8 | && go get -d -v \ 9 | && go build -o /go/bin/server 10 | 11 | #Build less reader 12 | FROM gcc:5.5 as builder_less 13 | 14 | WORKDIR /src/ 15 | 16 | RUN git clone https://github.com/vbwagner/less.git \ 17 | && cd less \ 18 | && sh configure --with-secure \ 19 | && make 20 | 21 | #Build redditbox server 22 | FROM ubuntu:18.04 23 | 24 | ENV DEBIAN_FRONTEND noninteractive 25 | ENV TERM linux 26 | 27 | RUN apt update -y -qq \ 28 | && apt install xinetd telnetd dialog rtv musl screen ca-certificates wget language-pack-en less -y -qq \ 29 | && locale-gen en_US \ 30 | && locale-gen en_US.UTF-8 \ 31 | && update-locale 32 | 33 | COPY app_scripts/telnet /etc/xinetd.d/telnet 34 | RUN echo "" > /etc/issue 35 | 36 | COPY app_scripts/motd /app/motd 37 | COPY --from=builder_ssh /go/bin/server /app/server 38 | 39 | RUN wget https://github.com/mholt/caddy/releases/download/v0.11.0/caddy_v0.11.0_linux_amd64.tar.gz \ 40 | && tar --extract --file=caddy_v0.11.0_linux_amd64.tar.gz caddy \ 41 | && rm caddy_v0.11.0_linux_amd64.tar.gz \ 42 | && mv caddy /usr/local/bin/ 43 | 44 | COPY app_scripts/web/ /app/web 45 | COPY app_scripts/Caddyfile /app/Caddyfile 46 | COPY app_scripts/wrapper /app/wrapper 47 | COPY app_scripts/login /app/login 48 | COPY app_scripts/entrypoint /app/entrypoint 49 | 50 | COPY --from=builder_less /src/less/less /bin/less 51 | COPY --from=builder_less /src/less/lessecho /bin/lessecho 52 | COPY --from=builder_less /src/less/lesskey /bin/lesskey 53 | 54 | RUN chmod -R +x /bin/les* \ 55 | && chmod -R +x /app 56 | 57 | EXPOSE 22 23 80 443 58 | CMD /app/entrypoint -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Alex Jarmoszuk 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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # If we have `--squash` support, then use it! 2 | ifneq ($(shell docker build --help 2>/dev/null | grep squash),) 3 | DOCKER_BUILD = docker build --squash 4 | else 5 | DOCKER_BUILD = docker build 6 | endif 7 | 8 | all: build 9 | 10 | build: Makefile Dockerfile 11 | $(DOCKER_BUILD) -t falkenssmaze/redditbox . 12 | @echo "Done!" 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RedditBox 2 | # ![Logo](https://ss.delta360.net/ss_66781e5148d56890563bed909125686e.png "Logo") 3 | View Reddit on SSH or Telnet. 4 | 5 | This project will allow you to view Reddit in the CLI via an application called [RTV](https://github.com/michael-lazar/rtv). 6 | 7 | 8 | To run this container, use the following (make sure you generate a RSA private key beforehand): 9 | ```bash 10 | docker run -it -d --name redditbox -p 80:80 -p 22:22 -p 23:23 -p 443:443 -v /id_rsa:/app/id_rsa:ro -v :/root/.caddy falkenssmaze/redditbox 11 | ``` 12 | 13 | 14 | RTV (Reddit Terminal Viewer) is developed by Michael Lazar, Redditbox.us is a independent project and has no official affiliation with RTV or Michael Lazar. 15 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Fixed Security Vurnabilities 2 | 3 | commit aea61b331db5e0b59d6c445e537d68c09aebb7bc - Fixed a less backdoor issue originally reported by [/u/gentlebendy](https://www.reddit.com/user/gentlebendy) on Reddit 4 | 5 | -------------------------------------------------------------------------------- /app_scripts/Caddyfile: -------------------------------------------------------------------------------- 1 | redditbox.us { 2 | root /app/web/ 3 | tls notify@delta360.net 4 | } 5 | -------------------------------------------------------------------------------- /app_scripts/entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd /app/ 3 | 4 | if [ ! -f /app/id_rsa ]; then 5 | ssh-keygen -f /app/id_rsa -t rsa -N '' 6 | fi 7 | 8 | service xinetd start 9 | screen -d -m /app/server 10 | caddy -agree 11 | -------------------------------------------------------------------------------- /app_scripts/login: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat /app/motd 4 | sleep 2 5 | /app/wrapper 6 | -------------------------------------------------------------------------------- /app_scripts/motd: -------------------------------------------------------------------------------- 1 | Welcome to 2 | _ _ _ _ _ _ 3 | | | | (_) | | (_) 4 | _ __ ___ __| | __| |_| |_ ___| |_ 5 | | '__/ _ \/ _` |/ _` | | __| / __| | | 6 | | | | __/ (_| | (_| | | |_ | (__| | | 7 | |_| \___|\__,_|\__,_|_|\__| \___|_|_| 8 | in the 9 | @redditbox.us 10 | 11 | Loading, please wait... 12 | -------------------------------------------------------------------------------- /app_scripts/ssh/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "io/ioutil" 7 | "log" 8 | "os" 9 | "os/exec" 10 | "syscall" 11 | "unsafe" 12 | "time" 13 | 14 | "github.com/gliderlabs/ssh" 15 | "github.com/kr/pty" 16 | ) 17 | 18 | func setWinsize(f *os.File, w, h int) { 19 | syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), uintptr(syscall.TIOCSWINSZ), 20 | uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(h), uint16(w), 0, 0}))) 21 | } 22 | 23 | func main() { 24 | ssh.Handle(func(s ssh.Session) { 25 | log.Printf("Connection from %s (%s)", s.RemoteAddr(), s.User()) 26 | b, err := ioutil.ReadFile("/app/motd") 27 | if err != nil { 28 | log.Print(err) 29 | } 30 | 31 | io.WriteString(s, string(b)) 32 | io.WriteString(s, fmt.Sprintf("Hello %s!\n", s.User())) 33 | time.Sleep(1 * time.Second) 34 | 35 | cmd := exec.Command("/app/wrapper") 36 | ptyReq, winCh, isPty := s.Pty() 37 | if isPty { 38 | cmd.Env = append(cmd.Env, fmt.Sprintf("TERM=%s", ptyReq.Term)) 39 | f, err := pty.Start(cmd) 40 | if err != nil { 41 | panic(err) 42 | } 43 | go func() { 44 | for win := range winCh { 45 | setWinsize(f, win.Width, win.Height) 46 | } 47 | }() 48 | go func() { 49 | io.Copy(f, s) // stdin 50 | }() 51 | io.Copy(s, f) // stdout 52 | } else { 53 | io.WriteString(s, "No PTY requested.\n") 54 | s.Exit(1) 55 | } 56 | }) 57 | 58 | log.Println("SSH server started...") 59 | log.Fatal(ssh.ListenAndServe(":22", nil, ssh.HostKeyFile("/app/id_rsa"))) 60 | } 61 | -------------------------------------------------------------------------------- /app_scripts/telnet: -------------------------------------------------------------------------------- 1 | service telnet 2 | { 3 | disable = no 4 | flags = REUSE 5 | socket_type = stream 6 | wait = no 7 | user = root 8 | server = /usr/sbin/in.telnetd 9 | server_args = -h -L /app/login 10 | log_on_failure += USERID 11 | } 12 | -------------------------------------------------------------------------------- /app_scripts/web/app.css: -------------------------------------------------------------------------------- 1 | @import url('termynal.css'); 2 | @import url('https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css'); 3 | @import url('https://fonts.googleapis.com/css?family=Oxygen+Mono'); 4 | 5 | .rainbow { 6 | -webkit-animation: rainbow 120s infinite; 7 | -ms-animation: rainbow 120s infinite; 8 | animation: rainbow 120s infinite; 9 | } 10 | 11 | @-webkit-keyframes rainbow{ 12 | 20%{color: red;} 13 | 40%{color: yellow;} 14 | 60%{color: green;} 15 | 80%{color: blue;} 16 | 100%{color: orange;} 17 | } 18 | 19 | @-ms-keyframes rainbow{ 20 | 20%{color: red;} 21 | 40%{color: yellow;} 22 | 60%{color: green;} 23 | 80%{color: blue;} 24 | 100%{color: orange;} 25 | } 26 | 27 | @keyframes rainbow{ 28 | 5%{color: red;} 29 | 35%{color: yellow;} 30 | 65%{color: green;} 31 | 85%{color: blue;} 32 | 0%{color: orange;} 33 | } 34 | 35 | .title { 36 | font-size: 26px !important; 37 | } 38 | 39 | body { 40 | overflow:hidden; 41 | } 42 | -------------------------------------------------------------------------------- /app_scripts/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ajarmoszuk/redditbox/9fb59c746ff927d1dc39766cbef60eab4bf61466/app_scripts/web/favicon.png -------------------------------------------------------------------------------- /app_scripts/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | RedditBox.us - Reddit via the CLI terminal (SSH/Telnet)! 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 29 | 30 | 31 | 32 | 33 | 34 |
35 |
36 |
37 |
38 |
39 | 40 |
 41 | 		
 42 | 
 43 | MMMMMMMMMMMMMMMMMMNmmddhhhhddmmNMMMMMMMMMMMMMMMMMM
 44 | MMMMMMMMMMMMMNdhysoooooooooooooosyhmNMMMMMMMMMMMMM
 45 | MMMMMMMMMMNdsoooooooooooooooooooooooosdNMMMMMMMMMM
 46 | MMMMMMMMmyooooooooooooooooo-`.-::/+/.`.-smMMMMMMMM
 47 | MMMMMMmyoooooooooooooooooo/ ./:--.`     .oymMMMMMM
 48 | MMMMMhoooooooooooooooooooo` +ooooo+`   `/ooohMMMMM
 49 | MMMNsoooooooooooooooooooo- :oooooooo+++oooooosNMMM
 50 | MMNsoooooooooooooo+::-...  --::/+ooooooooooooosNMM
 51 | MMyooooo/---:+/-`                `.:+/---:+ooooyMM
 52 | Mdoooo+`                                   /oooodM
 53 | Msoooo:                                    .ooooyM
 54 | Noooooo.         /ooo-      .+oo+`        `+oooooM
 55 | Nooooooo:       `oooo+      :oooo-       .oooooooN
 56 | Mooooooo/        `-:-        .:-`        -oooooooM
 57 | Msooooooo                                /oooooosM
 58 | Mdooooooo/        .+:.`    `.:+-        :ooooooodM
 59 | MMyooooooo+.       .:+oooooo+/-       `/oooooooyMM
 60 | MMNsoooooooo+-`         ``          -/oooooooosNMM
 61 | MMMNsoooooooooo+:-.`           `-:+oooooooooosNMMM
 62 | MMMMMhooooooooooooooo+++///++ooooooooooooooohMMMMM
 63 | MMMMMMmyooooooooooooooooooooooooooooooooooymMMMMMM
 64 | MMMMMMMMmyooooooooooooooooooooooooooooooymMMMMMMMM
 65 | MMMMMMMMMMNhsoooooooooooooooooooooooosdNMMMMMMMMMM
 66 | MMMMMMMMMMMMMNdhyooooooooooooooooyhdNMMMMMMMMMMMMM
 67 | MMMMMMMMMMMMMMMMMMNmddhhhhhdddmNMMMMMMMMMMMMMMMMMM
 68 | 
 69 | 				    REDDITBOX.US
 70 | 
 71 | 		
 72 |       
73 |
74 |
75 |

76 | Browse Reddit via Telnet/SSH!
77 |

78 | SSH: ssh redditbox.us
79 | Telnet: telnet redditbox.us
80 | 83 |

84 |
85 |

86 | A small side project by Alex Jarmoszuk.
87 | This site has no affiliation with Reddit or its subsidiaries. 88 |

89 |

90 |
91 | 92 |
93 |
94 |
95 |
96 |
97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /app_scripts/web/termynal.css: -------------------------------------------------------------------------------- 1 | /** 2 | * termynal.js 3 | * 4 | * @author Ines Montani 5 | * @version 0.0.1 6 | * @license MIT 7 | */ 8 | 9 | :root { 10 | --color-bg: #000; 11 | --color-text: #eee; 12 | --color-text-subtle: #a2a2a2; 13 | } 14 | 15 | [data-termynal] { 16 | width: 100%; 17 | max-width: 100%; 18 | background: var(--color-bg); 19 | color: var(--color-text); 20 | font-size: 18px; 21 | font-family: 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace; 22 | border-radius: 4px; 23 | padding: 75px 45px 35px; 24 | position: relative; 25 | -webkit-box-sizing: border-box; 26 | box-sizing: border-box; 27 | } 28 | 29 | [data-termynal]:before { 30 | content: ''; 31 | position: absolute; 32 | top: 15px; 33 | left: 15px; 34 | display: inline-block; 35 | width: 15px; 36 | height: 15px; 37 | border-radius: 50%; 38 | /* A little hack to display the window buttons in one pseudo element. */ 39 | background: #d9515d; 40 | -webkit-box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; 41 | box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; 42 | } 43 | 44 | [data-ty] { 45 | display: block; 46 | line-height: 2; 47 | } 48 | 49 | [data-ty]:before { 50 | /* Set up defaults and ensure empty lines are displayed. */ 51 | content: ''; 52 | display: inline-block; 53 | vertical-align: middle; 54 | } 55 | 56 | [data-ty="input"]:before, 57 | [data-ty-prompt]:before { 58 | margin-right: 0.75em; 59 | color: var(--color-text-subtle); 60 | } 61 | 62 | [data-ty="input"]:before { 63 | content: '$'; 64 | } 65 | 66 | [data-ty][data-ty-prompt]:before { 67 | content: attr(data-ty-prompt); 68 | } 69 | 70 | [data-ty-cursor]:after { 71 | content: attr(data-ty-cursor); 72 | font-family: monospace; 73 | margin-left: 0.5em; 74 | -webkit-animation: blink 1s infinite; 75 | animation: blink 1s infinite; 76 | } 77 | 78 | 79 | /* Cursor animation */ 80 | 81 | @-webkit-keyframes blink { 82 | 50% { 83 | opacity: 0; 84 | } 85 | } 86 | 87 | @keyframes blink { 88 | 50% { 89 | opacity: 0; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app_scripts/wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export LANGUAGE="en_US.UTF-8" 4 | export LC_ALL="en_US.UTF-8" 5 | 6 | HEIGHT=16 7 | WIDTH=48 8 | CHOICE_HEIGHT=6 9 | BACKTITLE="RedditBox.us" 10 | TITLE="Reddit CLI" 11 | MENU="Choose one of the following options:" 12 | 13 | OPTIONS=(1 "Reddit" 14 | 2 "Reddit Monochrome" 15 | 3 "Reddit Monokai" 16 | 4 "Reddit Papercolor" 17 | 5 "Reddit Solarized (Dark)" 18 | 6 "Reddit Solarized (Light)" 19 | ) 20 | 21 | 22 | CHOICE=$(dialog --clear \ 23 | --backtitle "$BACKTITLE" \ 24 | --title "$TITLE" \ 25 | --menu "$MENU" \ 26 | $HEIGHT $WIDTH $CHOICE_HEIGHT \ 27 | "${OPTIONS[@]}" \ 28 | 2>&1 >/dev/tty) 29 | 30 | clear 31 | case $CHOICE in 32 | 1) 33 | /usr/bin/rtv 34 | ;; 35 | 2) 36 | /usr/bin/rtv --monochrome 37 | ;; 38 | 3) 39 | /usr/bin/rtv --theme molokai 40 | ;; 41 | 4) 42 | /usr/bin/rtv --theme papercolor 43 | ;; 44 | 5) 45 | /usr/bin/rtv --theme solarized-dark 46 | ;; 47 | 6) 48 | /usr/bin/rtv --theme solarized-light 49 | ;; 50 | esac 51 | --------------------------------------------------------------------------------