Skip to content

Instantly share code, notes, and snippets.

@mehmetron
Last active August 13, 2021 19:27
Show Gist options
  • Save mehmetron/2daeb8d40ceb08b8f87204de8d82f45e to your computer and use it in GitHub Desktop.
Save mehmetron/2daeb8d40ceb08b8f87204de8d82f45e to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"fmt"
"io"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os/exec"
"strings"
"time"
"github.com/gorilla/websocket"
)
// ReverseProxy proxies requests
func ReverseProxy(w http.ResponseWriter, r *http.Request) {
fmt.Println("Request Info: ", r.Host, r.Method, r.Proto)
var rawUrl string
subdomain := strings.Split(r.Host, ".")[0]
fmt.Println("21 subdomain ", subdomain)
if subdomain == "pid1" {
rawUrl = "http://localhost:8100/"
} else {
rawUrl = "http://localhost:8200/"
}
parsedUrl, err := url.Parse(rawUrl)
if err != nil {
fmt.Println(err)
}
proxy := httputil.NewSingleHostReverseProxy(parsedUrl)
proxy.ServeHTTP(w, r)
}
func voidHandler2(w http.ResponseWriter, r *http.Request) {
fmt.Println("48 server 8200")
fmt.Fprint(w, "server 2 8200")
}
const (
// Time allowed to write a message to the peer.
writeWait = 10 * time.Second
// Time to wait before force close on connection.
closeGracePeriod = 10 * time.Second
)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
func pumpStdout(ws *websocket.Conn, r io.Reader, done chan struct{}) {
defer func() {
}()
s := bufio.NewScanner(r)
for s.Scan() {
ws.SetWriteDeadline(time.Now().Add(writeWait))
if err := ws.WriteMessage(websocket.TextMessage, s.Bytes()); err != nil {
ws.Close()
break
}
}
if s.Err() != nil {
fmt.Println("scan: ", s.Err())
}
close(done)
ws.SetWriteDeadline(time.Now().Add(writeWait))
ws.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
time.Sleep(closeGracePeriod)
ws.Close()
}
// Websocket route
func CmdToResponse(w http.ResponseWriter, r *http.Request) {
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
w.Write([]byte(fmt.Sprintf("", err)))
return
}
defer ws.Close()
fmt.Println("136 please work")
// discard received messages
go func(c *websocket.Conn) {
for {
if _, _, err := c.NextReader(); err != nil {
c.Close()
break
}
}
}(ws)
fmt.Println("146 please work")
ws.WriteMessage(1, []byte("Starting...\n"))
// execute and get a pipe
cmd := exec.Command("/bin/sh", "-c", "ls")
fmt.Println("161 please work")
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println("127 ", err)
return
}
stderr, err := cmd.StderrPipe()
if err != nil {
fmt.Println("132 ", err)
return
}
if err := cmd.Start(); err != nil {
fmt.Println("137 ", err)
return
}
stdoutDone := make(chan struct{})
go pumpStdout(ws, io.MultiReader(stdout, stderr), stdoutDone)
if err := cmd.Wait(); err != nil {
fmt.Println("155 ", err)
return
}
ws.WriteMessage(1, []byte("Finished\n"))
}
// Websocket html
var html = []byte(
`<html>
<body>
<h1>blah.exe</h1>
<code></code>
<script>
var ws = new WebSocket("ws://pid1.localhost:8000/ws")
ws.onmessage = function(e) {
console.log("87 message recieved ", e.data)
document.querySelector("code").innerHTML += e.data + "<br>"
}
</script>
</body>
</html>
`)
func ServeHtml(w http.ResponseWriter, r *http.Request) {
w.Write(html)
}
func main() {
myMux := http.NewServeMux()
myMux.HandleFunc("/", ServeHtml)
myMux.HandleFunc("/ws", CmdToResponse)
server := &http.Server{
Addr: ":8100",
Handler: myMux,
}
go server.ListenAndServe()
gorillaMux := http.NewServeMux()
gorillaMux.HandleFunc("/", voidHandler2)
server2 := &http.Server{
Addr: ":8200",
Handler: gorillaMux,
}
go server2.ListenAndServe()
router2 := http.NewServeMux()
router2.HandleFunc("/", ReverseProxy)
srv := &http.Server{
Handler: router2,
Addr: ":8000",
}
log.Fatal(srv.ListenAndServe())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment