Skip to content

Instantly share code, notes, and snippets.

@Atticuss
Created May 24, 2018 22:17
Show Gist options
  • Save Atticuss/80a1708e21aa2b5726b4a19ccbe9b275 to your computer and use it in GitHub Desktop.
Save Atticuss/80a1708e21aa2b5726b4a19ccbe9b275 to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"fmt"
"net"
"strconv"
"strings"
)
func main() {
ln, err := net.Listen("tcp", ":10000")
if err != nil {
fmt.Printf("unable to listen: %v", err)
return
}
defer ln.Close()
for {
conn, err := ln.Accept()
if err != nil {
// handle error
}
go handleConnection(conn)
}
}
func jwtToAddr(jwt string) string {
return "34.234.234.203:8085"
//return "127.0.0.1:10001"
}
func parseFromHeadersMap(headersMap map[string]string) (int, string, error) {
jwtCookieName := "auth_token"
var (
err error
clen int
jwt string
)
for k, v := range headersMap {
if k == "Content-Length" {
clen, err = strconv.Atoi(strings.TrimSpace(v))
}
if err != nil {
fmt.Printf("error parsing Content-Length header value: %v\n", err)
}
if k == "Cookie" {
cookies := strings.Split(strings.TrimSpace(v), ";")
for _, cookie := range cookies {
cookieSlice := strings.Split(cookie, "=")
if cookieSlice[0] == jwtCookieName {
jwt = cookieSlice[1]
fmt.Printf("jwt found: %v\n", jwt)
}
}
}
}
return clen, jwt, nil
}
func readHTTPHeader(reader *bufio.Reader) ([]byte, map[string]string, error) {
threshold := 5096
//reader := *readerp
headersMap := make(map[string]string)
status, err := reader.ReadString('\n')
bSlice := []byte(status)
bytesRead := bSlice
for err == nil {
status, err = reader.ReadString('\n')
bSlice = []byte(status)
bytesRead = append(bytesRead, bSlice...)
// if just len<=2, then we've finished reading the http headers
if len(status) <= 2 {
break
}
// to prevent a memdos, lets throw an error if the http header
// section is unusually large.
// TODO: throw an error
if len(bytesRead) >= threshold {
break
}
header := strings.Split(status, ":")
headersMap[header[0]] = header[1]
}
return bytesRead, headersMap, nil
}
func handleConnection(clientConn net.Conn) {
defer clientConn.Close()
clientReaderBuf := bufio.NewReader(clientConn)
clientWriterBuf := bufio.NewWriter(clientConn)
bytesRead, headersMap, err := readHTTPHeader(clientReaderBuf)
if err != nil {
fmt.Printf("err thrown reading client http header: %v\n", err)
return
}
clen, jwt, err := parseFromHeadersMap(headersMap)
if jwt == "" {
fmt.Println("jwt token not found -- returning error msg to user")
clientWriterBuf.Write([]byte("HTTP/1.1 500\r\nContent-Length: 46\r\n\r\n<html><body><h1>missing jwt</h1></body></html>"))
clientWriterBuf.Flush()
return
}
addr := jwtToAddr(jwt)
remoteConn, err := net.Dial("tcp", addr)
if err != nil {
fmt.Printf("Unable to reach remote server: %v\n", err)
return
}
defer remoteConn.Close()
serverReaderBuf := bufio.NewReader(remoteConn)
serverWriterBuf := bufio.NewWriter(remoteConn)
serverWriterBuf.Write(bytesRead)
if clen > 0 {
for i := 0; i < clen; i++ {
b, err := clientReaderBuf.ReadByte()
if err != nil {
fmt.Printf("Error reading client body: %v", err)
return
}
err = serverWriterBuf.WriteByte(b)
bytesRead = append(bytesRead, b)
if err != nil {
fmt.Printf("Error writing server body: %v", err)
return
}
}
} else {
//fmt.Println("Content-Length header not found in client req, not parsing for a body")
}
serverWriterBuf.Flush()
bytesRead, headersMap, err = readHTTPHeader(serverReaderBuf)
clen, _, err = parseFromHeadersMap(headersMap)
clientWriterBuf.Write(bytesRead)
if clen > 0 {
for i := 0; i < clen; i++ {
b, err := serverReaderBuf.ReadByte()
if err != nil {
fmt.Printf("Error reading server body: %v", err)
return
}
err = clientWriterBuf.WriteByte(b)
bytesRead = append(bytesRead, b)
if err != nil {
fmt.Printf("Error writing client body: %v", err)
return
}
}
} else {
//fmt.Println("Content-Length header not found in server resp, not parsing for a body")
}
clientWriterBuf.Flush()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment