2018-02-25 15:09:21 -05:00
/ *
maryo / proxy . go
the proxy that makes this program a reverse proxy
2018-03-14 15:11:00 -04:00
made by that magical 3 ds person
2018-02-25 15:09:21 -05:00
2018-04-10 14:36:30 -04:00
written by superwhiskers , licensed under gnu gplv3 .
2018-02-25 15:09:21 -05:00
if you want a copy , go to http : //www.gnu.org/licenses/
* /
package main
2018-03-14 15:11:00 -04:00
import (
2018-03-14 20:37:16 -04:00
// internals
2018-03-14 15:11:00 -04:00
"fmt"
2018-03-14 20:37:16 -04:00
"log"
"net/http"
2018-03-16 21:25:52 -04:00
"strings"
2018-03-20 16:43:23 -04:00
"time"
2018-03-20 21:46:54 -04:00
"net/http/httputil"
2018-03-14 20:37:16 -04:00
// externals
"github.com/elazarl/goproxy"
2018-03-14 15:11:00 -04:00
)
2018-03-14 20:37:16 -04:00
2018-03-13 20:20:16 -04:00
//"os"
2018-03-14 20:37:16 -04:00
// set this over here for no issues
var config map [ string ] interface { }
2018-02-25 15:09:21 -05:00
2018-03-16 14:54:57 -04:00
func startProxy ( configName string , logging bool ) {
2018-02-25 15:09:21 -05:00
2018-03-13 20:20:16 -04:00
// set the terminal title
ttitle ( "maryo -> proxy" )
// get the config data
2018-03-14 20:37:16 -04:00
config = readJSONFile ( configName )
2018-03-20 18:41:43 -04:00
// check if we decrypt all connections
decryptAll := config [ "config" ] . ( map [ string ] interface { } ) [ "decryptOutgoing" ] . ( string )
2018-03-20 16:43:23 -04:00
// check if log file exists
2018-04-10 14:36:30 -04:00
if doesFileExist ( "maryo-data/proxy.log" ) == false {
2018-03-14 20:37:16 -04:00
2018-03-20 16:43:23 -04:00
// make it then
2018-04-10 14:36:30 -04:00
createFile ( "maryo-data/proxy.log" )
2018-03-20 16:43:23 -04:00
}
// write current timestamp to log
t := time . Now ( ) . Format ( "20060102150405" )
2018-04-10 14:36:30 -04:00
writeFile ( "maryo-data/proxy.log" , fmt . Sprintf ( "-> started log [%s]\n" , t ) )
2018-03-20 16:43:23 -04:00
// get ip
ip := getIP ( )
// start the console log
2018-03-14 20:37:16 -04:00
fmt . Printf ( "-- proxy log --\n" )
2018-03-20 16:43:23 -04:00
consoleSequence ( fmt . Sprintf ( "-> local IP address is %s%s%s\n" , code ( "green" ) , ip , code ( "reset" ) ) )
2018-03-14 20:37:16 -04:00
consoleSequence ( fmt . Sprintf ( "-> hosting proxy on %s:9437%s\n" , code ( "green" ) , code ( "reset" ) ) )
2018-04-10 14:36:30 -04:00
writeFile ( "maryo-data/proxy.log" , fmt . Sprintf ( "-> got local ip as %s, hosting on port :9437" , ip ) )
2018-03-14 15:11:00 -04:00
2018-03-14 20:37:16 -04:00
// load that proxy
proxy := goproxy . NewProxyHttpServer ( )
2018-03-16 19:53:38 -04:00
// set some settings
2018-03-16 21:25:52 -04:00
2018-03-20 20:17:12 -04:00
// http client for use when performing POST requests
httpClient := & http . Client { }
2018-03-20 18:41:43 -04:00
// add the ninty cert and key to the proxy for decrypting
setCA ( nintyCert , nintyKey )
2018-03-16 21:25:52 -04:00
// verbose mode can be a little... too verbose
proxy . Verbose = logging
2018-03-16 19:53:38 -04:00
// set up the proxy
2018-03-16 21:25:52 -04:00
// make it always MITM
proxy . OnRequest ( ) . HandleConnect ( goproxy . AlwaysMitm )
2018-03-16 19:53:38 -04:00
// request handler
proxy . OnRequest ( ) . DoFunc (
func ( r * http . Request , ctx * goproxy . ProxyCtx ) ( * http . Request , * http . Response ) {
// log the request
consoleSequence ( fmt . Sprintf ( "-> request to %s%s%s\n" , code ( "green" ) , r . URL . Host , code ( "reset" ) ) )
2018-04-10 14:36:30 -04:00
writeFile ( "maryo-data/proxy.log" , fmt . Sprintf ( "-> got request to %s\n" , r . URL . Host ) )
2018-03-20 16:43:23 -04:00
// get prettified request
2018-03-21 01:12:37 -04:00
// define these variables so no errors
var reqData [ ] byte
var err error
// no errors for post requests
if r . Method == "POST" {
// if it is, then tell the dumper it is
reqData , err = httputil . DumpRequest ( r , true )
} else {
// otherwise, don't
reqData , err = httputil . DumpRequest ( r , false )
}
2018-03-20 21:46:54 -04:00
if err != nil {
// output error
fmt . Printf ( "[err]: error occurred while dumping http request\n" )
fmt . Printf ( "%s\n" , err . Error ( ) )
}
2018-03-16 21:25:52 -04:00
// if it is said to be verbose with logging, print request data
2018-03-20 16:43:23 -04:00
if logging == true {
// log the request data, then
fmt . Printf ( "\n-- request data\n" )
2018-03-21 01:12:37 -04:00
fmt . Printf ( "%s" , string ( reqData [ : ] ) )
2018-03-20 16:43:23 -04:00
fmt . Printf ( "\n\n" )
}
// always log to file
2018-04-10 14:36:30 -04:00
writeFile ( "maryo-data/proxy.log" , fmt . Sprintf ( "-> request data to %s\n" , r . URL . Host ) )
writeFile ( "maryo-data/proxy.log" , fmt . Sprintf ( "%s" , string ( reqData [ : ] ) ) )
writeFile ( "maryo-data/proxy.log" , fmt . Sprintf ( "\n\n" ) )
2018-03-16 19:53:38 -04:00
2018-03-16 21:25:52 -04:00
// attempt to proxy it to the servers listed in config
// check if it is in it in the first place
// also, strip the URL of the port
2018-03-20 18:41:43 -04:00
if redirTo , isItIn := config [ "endpoints" ] . ( map [ string ] interface { } ) [ strings . Split ( r . URL . Host , ":" ) [ 0 ] ] . ( string ) ; isItIn {
// check if we decrypt all outgoing connections
if decryptAll == "true" {
// if protocol is HTTPS
if r . URL . Scheme == "https" {
// let the user know
fmt . Printf ( "-> switching protocol to http\n" )
2018-03-16 19:53:38 -04:00
2018-03-20 18:41:43 -04:00
// set it to HTTP
r . URL . Scheme = "http"
2018-03-16 19:53:38 -04:00
2018-03-20 18:41:43 -04:00
}
2018-03-16 19:53:38 -04:00
2018-03-20 18:41:43 -04:00
}
2018-03-16 21:25:52 -04:00
// log the redirect
2018-03-20 18:41:43 -04:00
consoleSequence ( fmt . Sprintf ( "-> proxying %s%s%s to %s%s%s\n" , code ( "green" ) , r . URL . Host , code ( "reset" ) , code ( "green" ) , redirTo , code ( "reset" ) ) )
2018-04-10 14:36:30 -04:00
writeFile ( "maryo-data/proxy.log" , fmt . Sprintf ( "-> proxying %s to %s" , r . URL . Host , redirTo ) )
2018-03-16 19:53:38 -04:00
// redirect it
2018-03-20 18:41:43 -04:00
r . URL . Host = redirTo
2018-03-16 19:53:38 -04:00
2018-03-16 21:25:52 -04:00
}
2018-03-16 19:53:38 -04:00
2018-03-20 20:17:12 -04:00
// here is a fancy workaround for POST requests
if r . Method == "POST" {
// show the user that we performed a POST request
fmt . Printf ( "-> performing %s request to %s%s://%s%s%s\n" , r . Method , code ( "green" ) , r . URL . Scheme , r . URL . Host , r . URL . Path , code ( "reset" ) )
// clone the request
newReq := cloneReq ( r )
// perform the request
resp , err := httpClient . Do ( newReq )
// error handling
if err != nil {
2018-03-20 21:46:54 -04:00
2018-03-20 20:17:12 -04:00
// return a response
return r , goproxy . NewResponse ( newReq , goproxy . ContentTypeText , http . StatusBadGateway , strings . Join ( [ ] string { "no worries, this is an error in maryo\n" , err . Error ( ) } , "" ) )
}
2018-03-20 21:46:54 -04:00
// dump response
2018-03-21 01:12:37 -04:00
// make these variables earlier on so no errors
var fmtResp [ ] byte
// check if the request is a post request
if r . Method == "POST" {
// if so, tell the dumper that it is one
fmtResp , err = httputil . DumpResponse ( resp , true )
} else {
// otherwise, don't
fmtResp , err = httputil . DumpResponse ( resp , false )
}
2018-03-20 21:46:54 -04:00
// error handling
if err != nil {
// log the error
fmt . Printf ( "[err]: error while dumping response" )
fmt . Printf ( "%s\n" , err . Error ( ) )
}
// make sure the user wants to log response data
if logging == true {
// log it if they do
fmt . Printf ( "\n-- response data\n" )
2018-03-21 01:12:37 -04:00
fmt . Printf ( "%s\n" , string ( fmtResp [ : ] ) )
2018-03-20 21:46:54 -04:00
fmt . Printf ( "\n\n" )
}
2018-03-20 20:17:12 -04:00
// return the processed response
2018-03-20 21:46:54 -04:00
return r , resp
2018-03-20 20:17:12 -04:00
}
2018-03-16 21:25:52 -04:00
// just return nil for response, since we aren't modifying it
return r , nil
} )
2018-03-16 19:53:38 -04:00
// start the proxy
2018-03-14 20:37:16 -04:00
log . Fatal ( http . ListenAndServe ( ":9437" , proxy ) )
2018-03-21 02:53:49 -04:00
2018-02-25 15:09:21 -05:00
}