Created
May 24, 2018 22:17
-
-
Save Atticuss/80a1708e21aa2b5726b4a19ccbe9b275 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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