|
|
@ -2,6 +2,7 @@ package main |
|
|
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
import ( |
|
|
|
"crypto/tls" |
|
|
|
"crypto/tls" |
|
|
|
|
|
|
|
"encoding/base64" |
|
|
|
"fmt" |
|
|
|
"fmt" |
|
|
|
"log" |
|
|
|
"log" |
|
|
|
"net" |
|
|
|
"net" |
|
|
@ -15,6 +16,9 @@ import ( |
|
|
|
var getNextSubId = IdCounter() |
|
|
|
var getNextSubId = IdCounter() |
|
|
|
var getNextStorageId = IdCounter() |
|
|
|
var getNextStorageId = IdCounter() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Working on using this for webui
|
|
|
|
|
|
|
|
type proxyWebUIHandler func(http.ResponseWriter, *http.Request, *InterceptingProxy) |
|
|
|
|
|
|
|
|
|
|
|
type savedStorage struct { |
|
|
|
type savedStorage struct { |
|
|
|
storage MessageStorage |
|
|
|
storage MessageStorage |
|
|
|
description string |
|
|
|
description string |
|
|
@ -26,6 +30,13 @@ type InterceptingProxy struct { |
|
|
|
mtx sync.Mutex |
|
|
|
mtx sync.Mutex |
|
|
|
logger *log.Logger |
|
|
|
logger *log.Logger |
|
|
|
proxyStorage int |
|
|
|
proxyStorage int |
|
|
|
|
|
|
|
netDial NetDialer |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
usingProxy bool |
|
|
|
|
|
|
|
proxyHost string |
|
|
|
|
|
|
|
proxyPort int |
|
|
|
|
|
|
|
proxyIsSOCKS bool |
|
|
|
|
|
|
|
proxyCreds *ProxyCredentials |
|
|
|
|
|
|
|
|
|
|
|
requestInterceptor RequestInterceptor |
|
|
|
requestInterceptor RequestInterceptor |
|
|
|
responseInterceptor ResponseInterceptor |
|
|
|
responseInterceptor ResponseInterceptor |
|
|
@ -37,18 +48,20 @@ type InterceptingProxy struct { |
|
|
|
rspSubs []*RspIntSub |
|
|
|
rspSubs []*RspIntSub |
|
|
|
wsSubs []*WSIntSub |
|
|
|
wsSubs []*WSIntSub |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
httpHandlers map[string]proxyWebUIHandler |
|
|
|
|
|
|
|
|
|
|
|
messageStorage map[int]*savedStorage |
|
|
|
messageStorage map[int]*savedStorage |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type ProxyCredentials struct { |
|
|
|
|
|
|
|
Username string |
|
|
|
|
|
|
|
Password string |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type RequestInterceptor func(req *ProxyRequest) (*ProxyRequest, error) |
|
|
|
type RequestInterceptor func(req *ProxyRequest) (*ProxyRequest, error) |
|
|
|
type ResponseInterceptor func(req *ProxyRequest, rsp *ProxyResponse) (*ProxyResponse, error) |
|
|
|
type ResponseInterceptor func(req *ProxyRequest, rsp *ProxyResponse) (*ProxyResponse, error) |
|
|
|
type WSInterceptor func(req *ProxyRequest, rsp *ProxyResponse, msg *ProxyWSMessage) (*ProxyWSMessage, error) |
|
|
|
type WSInterceptor func(req *ProxyRequest, rsp *ProxyResponse, msg *ProxyWSMessage) (*ProxyWSMessage, error) |
|
|
|
|
|
|
|
|
|
|
|
type proxyHandler struct { |
|
|
|
|
|
|
|
Logger *log.Logger |
|
|
|
|
|
|
|
IProxy *InterceptingProxy |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type ReqIntSub struct { |
|
|
|
type ReqIntSub struct { |
|
|
|
id int |
|
|
|
id int |
|
|
|
Interceptor RequestInterceptor |
|
|
|
Interceptor RequestInterceptor |
|
|
@ -64,12 +77,19 @@ type WSIntSub struct { |
|
|
|
Interceptor WSInterceptor |
|
|
|
Interceptor WSInterceptor |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (creds *ProxyCredentials) SerializeHeader() string { |
|
|
|
|
|
|
|
toEncode := []byte(fmt.Sprintf("%s:%s", creds.Username, creds.Password)) |
|
|
|
|
|
|
|
encoded := base64.StdEncoding.EncodeToString(toEncode) |
|
|
|
|
|
|
|
return fmt.Sprintf("Basic %s", encoded) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func NewInterceptingProxy(logger *log.Logger) *InterceptingProxy { |
|
|
|
func NewInterceptingProxy(logger *log.Logger) *InterceptingProxy { |
|
|
|
var iproxy InterceptingProxy |
|
|
|
var iproxy InterceptingProxy |
|
|
|
iproxy.messageStorage = make(map[int]*savedStorage) |
|
|
|
iproxy.messageStorage = make(map[int]*savedStorage) |
|
|
|
iproxy.slistener = NewProxyListener(logger) |
|
|
|
iproxy.slistener = NewProxyListener(logger) |
|
|
|
iproxy.server = newProxyServer(logger, &iproxy) |
|
|
|
iproxy.server = newProxyServer(logger, &iproxy) |
|
|
|
iproxy.logger = logger |
|
|
|
iproxy.logger = logger |
|
|
|
|
|
|
|
iproxy.httpHandlers = make(map[string]proxyWebUIHandler) |
|
|
|
|
|
|
|
|
|
|
|
go func() { |
|
|
|
go func() { |
|
|
|
iproxy.server.Serve(iproxy.slistener) |
|
|
|
iproxy.server.Serve(iproxy.slistener) |
|
|
@ -93,7 +113,7 @@ func (iproxy *InterceptingProxy) SetCACertificate(caCert *tls.Certificate) { |
|
|
|
iproxy.slistener.SetCACertificate(caCert) |
|
|
|
iproxy.slistener.SetCACertificate(caCert) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) GetCACertificate() (*tls.Certificate) { |
|
|
|
func (iproxy *InterceptingProxy) GetCACertificate() *tls.Certificate { |
|
|
|
return iproxy.slistener.GetCACertificate() |
|
|
|
return iproxy.slistener.GetCACertificate() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -119,7 +139,7 @@ func (iproxy *InterceptingProxy) GetMessageStorage(id int) (MessageStorage, stri |
|
|
|
return savedStorage.storage, savedStorage.description |
|
|
|
return savedStorage.storage, savedStorage.description |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) AddMessageStorage(storage MessageStorage, description string) (int) { |
|
|
|
func (iproxy *InterceptingProxy) AddMessageStorage(storage MessageStorage, description string) int { |
|
|
|
iproxy.mtx.Lock() |
|
|
|
iproxy.mtx.Lock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
id := getNextStorageId() |
|
|
|
id := getNextStorageId() |
|
|
@ -190,7 +210,7 @@ func (iproxy *InterceptingProxy) LoadScope(storageId int) error { |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) GetScopeChecker() (RequestChecker) { |
|
|
|
func (iproxy *InterceptingProxy) GetScopeChecker() RequestChecker { |
|
|
|
iproxy.mtx.Lock() |
|
|
|
iproxy.mtx.Lock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
return iproxy.scopeChecker |
|
|
|
return iproxy.scopeChecker |
|
|
@ -212,19 +232,19 @@ func (iproxy *InterceptingProxy) SetScopeChecker(checker RequestChecker) error { |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) GetScopeQuery() (MessageQuery) { |
|
|
|
func (iproxy *InterceptingProxy) GetScopeQuery() MessageQuery { |
|
|
|
iproxy.mtx.Lock() |
|
|
|
iproxy.mtx.Lock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
return iproxy.scopeQuery |
|
|
|
return iproxy.scopeQuery |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) SetScopeQuery(query MessageQuery) (error) { |
|
|
|
func (iproxy *InterceptingProxy) SetScopeQuery(query MessageQuery) error { |
|
|
|
iproxy.mtx.Lock() |
|
|
|
iproxy.mtx.Lock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
return iproxy.setScopeQuery(query) |
|
|
|
return iproxy.setScopeQuery(query) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) setScopeQuery(query MessageQuery) (error) { |
|
|
|
func (iproxy *InterceptingProxy) setScopeQuery(query MessageQuery) error { |
|
|
|
checker, err := CheckerFromMessageQuery(query) |
|
|
|
checker, err := CheckerFromMessageQuery(query) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
@ -244,7 +264,48 @@ func (iproxy *InterceptingProxy) setScopeQuery(query MessageQuery) (error) { |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) ClearScope() (error) { |
|
|
|
func (iproxy *InterceptingProxy) SetNetDial(dialer NetDialer) { |
|
|
|
|
|
|
|
iproxy.mtx.Lock() |
|
|
|
|
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
|
|
|
|
iproxy.netDial = dialer |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) NetDial() NetDialer { |
|
|
|
|
|
|
|
iproxy.mtx.Lock() |
|
|
|
|
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
|
|
|
|
return iproxy.netDial |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) ClearUpstreamProxy() { |
|
|
|
|
|
|
|
iproxy.mtx.Lock() |
|
|
|
|
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
|
|
|
|
iproxy.usingProxy = false |
|
|
|
|
|
|
|
iproxy.proxyHost = "" |
|
|
|
|
|
|
|
iproxy.proxyPort = 0 |
|
|
|
|
|
|
|
iproxy.proxyIsSOCKS = false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) SetUpstreamProxy(proxyHost string, proxyPort int, creds *ProxyCredentials) { |
|
|
|
|
|
|
|
iproxy.mtx.Lock() |
|
|
|
|
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
|
|
|
|
iproxy.usingProxy = true |
|
|
|
|
|
|
|
iproxy.proxyHost = proxyHost |
|
|
|
|
|
|
|
iproxy.proxyPort = proxyPort |
|
|
|
|
|
|
|
iproxy.proxyIsSOCKS = false |
|
|
|
|
|
|
|
iproxy.proxyCreds = creds |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) SetUpstreamSOCKSProxy(proxyHost string, proxyPort int, creds *ProxyCredentials) { |
|
|
|
|
|
|
|
iproxy.mtx.Lock() |
|
|
|
|
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
|
|
|
|
iproxy.usingProxy = true |
|
|
|
|
|
|
|
iproxy.proxyHost = proxyHost |
|
|
|
|
|
|
|
iproxy.proxyPort = proxyPort |
|
|
|
|
|
|
|
iproxy.proxyIsSOCKS = true |
|
|
|
|
|
|
|
iproxy.proxyCreds = creds |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) ClearScope() error { |
|
|
|
iproxy.mtx.Lock() |
|
|
|
iproxy.mtx.Lock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
iproxy.scopeChecker = nil |
|
|
|
iproxy.scopeChecker = nil |
|
|
@ -262,7 +323,37 @@ func (iproxy *InterceptingProxy) ClearScope() (error) { |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) AddReqIntSub(f RequestInterceptor) (*ReqIntSub) { |
|
|
|
func (iproxy *InterceptingProxy) SubmitRequest(req *ProxyRequest) error { |
|
|
|
|
|
|
|
oldDial := req.NetDial |
|
|
|
|
|
|
|
defer func() { req.NetDial = oldDial }() |
|
|
|
|
|
|
|
req.NetDial = iproxy.NetDial() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if iproxy.usingProxy { |
|
|
|
|
|
|
|
if iproxy.proxyIsSOCKS { |
|
|
|
|
|
|
|
return SubmitRequestSOCKSProxy(req, iproxy.proxyHost, iproxy.proxyPort, iproxy.proxyCreds) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return SubmitRequestProxy(req, iproxy.proxyHost, iproxy.proxyPort, iproxy.proxyCreds) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return SubmitRequest(req) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) WSDial(req *ProxyRequest) (*WSSession, error) { |
|
|
|
|
|
|
|
oldDial := req.NetDial |
|
|
|
|
|
|
|
defer func() { req.NetDial = oldDial }() |
|
|
|
|
|
|
|
req.NetDial = iproxy.NetDial() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if iproxy.usingProxy { |
|
|
|
|
|
|
|
if iproxy.proxyIsSOCKS { |
|
|
|
|
|
|
|
return WSDialSOCKSProxy(req, iproxy.proxyHost, iproxy.proxyPort, iproxy.proxyCreds) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return WSDialProxy(req, iproxy.proxyHost, iproxy.proxyPort, iproxy.proxyCreds) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return WSDial(req) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) AddReqIntSub(f RequestInterceptor) *ReqIntSub { |
|
|
|
iproxy.mtx.Lock() |
|
|
|
iproxy.mtx.Lock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
|
|
|
|
|
|
|
@ -286,7 +377,7 @@ func (iproxy *InterceptingProxy) RemoveReqIntSub(sub *ReqIntSub) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) AddRspIntSub(f ResponseInterceptor) (*RspIntSub) { |
|
|
|
func (iproxy *InterceptingProxy) AddRspIntSub(f ResponseInterceptor) *RspIntSub { |
|
|
|
iproxy.mtx.Lock() |
|
|
|
iproxy.mtx.Lock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
|
|
|
|
|
|
|
@ -310,7 +401,7 @@ func (iproxy *InterceptingProxy) RemoveRspIntSub(sub *RspIntSub) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) AddWSIntSub(f WSInterceptor) (*WSIntSub) { |
|
|
|
func (iproxy *InterceptingProxy) AddWSIntSub(f WSInterceptor) *WSIntSub { |
|
|
|
iproxy.mtx.Lock() |
|
|
|
iproxy.mtx.Lock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
|
|
|
|
|
|
|
@ -360,6 +451,28 @@ func (iproxy *InterceptingProxy) GetProxyStorage() MessageStorage { |
|
|
|
return savedStorage.storage |
|
|
|
return savedStorage.storage |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) AddHTTPHandler(host string, handler proxyWebUIHandler) { |
|
|
|
|
|
|
|
iproxy.mtx.Lock() |
|
|
|
|
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
|
|
|
|
iproxy.httpHandlers[host] = handler |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) GetHTTPHandler(host string) (proxyWebUIHandler, error) { |
|
|
|
|
|
|
|
iproxy.mtx.Lock() |
|
|
|
|
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
|
|
|
|
handler, ok := iproxy.httpHandlers[host] |
|
|
|
|
|
|
|
if !ok { |
|
|
|
|
|
|
|
return nil, fmt.Errorf("no handler for host %s", host) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return handler, nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (iproxy *InterceptingProxy) RemoveHTTPHandler(host string) { |
|
|
|
|
|
|
|
iproxy.mtx.Lock() |
|
|
|
|
|
|
|
defer iproxy.mtx.Unlock() |
|
|
|
|
|
|
|
delete(iproxy.httpHandlers, host) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func ParseProxyRequest(r *http.Request) (*ProxyRequest, error) { |
|
|
|
func ParseProxyRequest(r *http.Request) (*ProxyRequest, error) { |
|
|
|
host, port, useTLS, err := DecodeRemoteAddr(r.RemoteAddr) |
|
|
|
host, port, useTLS, err := DecodeRemoteAddr(r.RemoteAddr) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
@ -382,14 +495,19 @@ func ErrResponse(w http.ResponseWriter, err error) { |
|
|
|
http.Error(w, err.Error(), http.StatusInternalServerError) |
|
|
|
http.Error(w, err.Error(), http.StatusInternalServerError) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
func (iproxy *InterceptingProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
|
|
|
|
handler, err := iproxy.GetHTTPHandler(r.Host) |
|
|
|
|
|
|
|
if err == nil { |
|
|
|
|
|
|
|
handler(w, r, iproxy) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
req, _ := ParseProxyRequest(r) |
|
|
|
req, _ := ParseProxyRequest(r) |
|
|
|
p.Logger.Println("Received request to", req.FullURL().String()) |
|
|
|
iproxy.logger.Println("Received request to", req.FullURL().String()) |
|
|
|
req.StripProxyHeaders() |
|
|
|
req.StripProxyHeaders() |
|
|
|
|
|
|
|
|
|
|
|
ms := p.IProxy.GetProxyStorage() |
|
|
|
ms := iproxy.GetProxyStorage() |
|
|
|
scopeChecker := p.IProxy.GetScopeChecker() |
|
|
|
scopeChecker := iproxy.GetScopeChecker() |
|
|
|
|
|
|
|
|
|
|
|
// Helper functions
|
|
|
|
// Helper functions
|
|
|
|
checkScope := func(req *ProxyRequest) bool { |
|
|
|
checkScope := func(req *ProxyRequest) bool { |
|
|
@ -415,10 +533,10 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
|
|
|
|
|
|
|
|
mangleRequest := func(req *ProxyRequest) (*ProxyRequest, bool, error) { |
|
|
|
mangleRequest := func(req *ProxyRequest) (*ProxyRequest, bool, error) { |
|
|
|
newReq := req.Clone() |
|
|
|
newReq := req.Clone() |
|
|
|
reqSubs := p.IProxy.getRequestSubs() |
|
|
|
reqSubs := iproxy.getRequestSubs() |
|
|
|
for _, sub := range reqSubs { |
|
|
|
for _, sub := range reqSubs { |
|
|
|
var err error = nil |
|
|
|
var err error = nil |
|
|
|
newReq, err := sub.Interceptor(newReq) |
|
|
|
newReq, err = sub.Interceptor(newReq) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
e := fmt.Errorf("error with request interceptor: %s", err) |
|
|
|
e := fmt.Errorf("error with request interceptor: %s", err) |
|
|
|
return nil, false, e |
|
|
|
return nil, false, e |
|
|
@ -431,7 +549,7 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
if newReq != nil { |
|
|
|
if newReq != nil { |
|
|
|
newReq.StartDatetime = time.Now() |
|
|
|
newReq.StartDatetime = time.Now() |
|
|
|
if !req.Eq(newReq) { |
|
|
|
if !req.Eq(newReq) { |
|
|
|
p.Logger.Println("Request modified by interceptor") |
|
|
|
iproxy.logger.Println("Request modified by interceptor") |
|
|
|
return newReq, true, nil |
|
|
|
return newReq, true, nil |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -443,10 +561,10 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
mangleResponse := func(req *ProxyRequest, rsp *ProxyResponse) (*ProxyResponse, bool, error) { |
|
|
|
mangleResponse := func(req *ProxyRequest, rsp *ProxyResponse) (*ProxyResponse, bool, error) { |
|
|
|
reqCopy := req.Clone() |
|
|
|
reqCopy := req.Clone() |
|
|
|
newRsp := rsp.Clone() |
|
|
|
newRsp := rsp.Clone() |
|
|
|
rspSubs := p.IProxy.getResponseSubs() |
|
|
|
rspSubs := iproxy.getResponseSubs() |
|
|
|
p.Logger.Printf("%d interceptors", len(rspSubs)) |
|
|
|
iproxy.logger.Printf("%d interceptors", len(rspSubs)) |
|
|
|
for _, sub := range rspSubs { |
|
|
|
for _, sub := range rspSubs { |
|
|
|
p.Logger.Println("mangling rsp...") |
|
|
|
iproxy.logger.Println("mangling rsp...") |
|
|
|
var err error = nil |
|
|
|
var err error = nil |
|
|
|
newRsp, err = sub.Interceptor(reqCopy, newRsp) |
|
|
|
newRsp, err = sub.Interceptor(reqCopy, newRsp) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
@ -460,7 +578,7 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
|
|
|
|
|
|
|
|
if newRsp != nil { |
|
|
|
if newRsp != nil { |
|
|
|
if !rsp.Eq(newRsp) { |
|
|
|
if !rsp.Eq(newRsp) { |
|
|
|
p.Logger.Println("Response for", req.FullURL(), "modified by interceptor") |
|
|
|
iproxy.logger.Println("Response for", req.FullURL(), "modified by interceptor") |
|
|
|
// it was mangled
|
|
|
|
// it was mangled
|
|
|
|
return newRsp, true, nil |
|
|
|
return newRsp, true, nil |
|
|
|
} |
|
|
|
} |
|
|
@ -477,7 +595,7 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
newMsg := ws.Clone() |
|
|
|
newMsg := ws.Clone() |
|
|
|
reqCopy := req.Clone() |
|
|
|
reqCopy := req.Clone() |
|
|
|
rspCopy := rsp.Clone() |
|
|
|
rspCopy := rsp.Clone() |
|
|
|
wsSubs := p.IProxy.getWSSubs() |
|
|
|
wsSubs := iproxy.getWSSubs() |
|
|
|
for _, sub := range wsSubs { |
|
|
|
for _, sub := range wsSubs { |
|
|
|
var err error = nil |
|
|
|
var err error = nil |
|
|
|
newMsg, err = sub.Interceptor(reqCopy, rspCopy, newMsg) |
|
|
|
newMsg, err = sub.Interceptor(reqCopy, rspCopy, newMsg) |
|
|
@ -494,7 +612,7 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
if !ws.Eq(newMsg) { |
|
|
|
if !ws.Eq(newMsg) { |
|
|
|
newMsg.Timestamp = time.Now() |
|
|
|
newMsg.Timestamp = time.Now() |
|
|
|
newMsg.Direction = ws.Direction |
|
|
|
newMsg.Direction = ws.Direction |
|
|
|
p.Logger.Println("Message modified by interceptor") |
|
|
|
iproxy.logger.Println("Message modified by interceptor") |
|
|
|
return newMsg, true, nil |
|
|
|
return newMsg, true, nil |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -503,7 +621,6 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
return ws, false, nil |
|
|
|
return ws, false, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
req.StartDatetime = time.Now() |
|
|
|
req.StartDatetime = time.Now() |
|
|
|
|
|
|
|
|
|
|
|
if checkScope(req) { |
|
|
|
if checkScope(req) { |
|
|
@ -537,12 +654,12 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if req.IsWSUpgrade() { |
|
|
|
if req.IsWSUpgrade() { |
|
|
|
p.Logger.Println("Detected websocket request. Upgrading...") |
|
|
|
iproxy.logger.Println("Detected websocket request. Upgrading...") |
|
|
|
|
|
|
|
|
|
|
|
rc, err := req.WSDial() |
|
|
|
rc, err := iproxy.WSDial(req) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
p.Logger.Println("error dialing ws server:", err) |
|
|
|
iproxy.logger.Println("error dialing ws server:", err) |
|
|
|
http.Error(w, err.Error(), http.StatusInternalServerError) |
|
|
|
http.Error(w, fmt.Sprintf("error dialing websocket server: %s", err.Error()), http.StatusInternalServerError) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
defer rc.Close() |
|
|
|
defer rc.Close() |
|
|
@ -560,8 +677,8 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
|
|
|
|
|
|
|
|
lc, err := upgrader.Upgrade(w, r, nil) |
|
|
|
lc, err := upgrader.Upgrade(w, r, nil) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
p.Logger.Println("error upgrading connection:", err) |
|
|
|
iproxy.logger.Println("error upgrading connection:", err) |
|
|
|
http.Error(w, err.Error(), http.StatusInternalServerError) |
|
|
|
http.Error(w, fmt.Sprintf("error upgrading connection: %s", err.Error()), http.StatusInternalServerError) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
defer lc.Close() |
|
|
|
defer lc.Close() |
|
|
@ -581,13 +698,13 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
mtype, msg, err := rc.ReadMessage() |
|
|
|
mtype, msg, err := rc.ReadMessage() |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
lc.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) |
|
|
|
lc.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) |
|
|
|
p.Logger.Println("error with receiving server message:", err) |
|
|
|
iproxy.logger.Println("error with receiving server message:", err) |
|
|
|
wg.Done() |
|
|
|
wg.Done() |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
pws, err := NewProxyWSMessage(mtype, msg, ToClient) |
|
|
|
pws, err := NewProxyWSMessage(mtype, msg, ToClient) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
p.Logger.Println("error creating ws object:", err.Error()) |
|
|
|
iproxy.logger.Println("error creating ws object:", err.Error()) |
|
|
|
continue |
|
|
|
continue |
|
|
|
} |
|
|
|
} |
|
|
|
pws.Timestamp = time.Now() |
|
|
|
pws.Timestamp = time.Now() |
|
|
@ -595,7 +712,7 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
if checkScope(req) { |
|
|
|
if checkScope(req) { |
|
|
|
newMsg, mangled, err := mangleWS(req, req.ServerResponse, pws) |
|
|
|
newMsg, mangled, err := mangleWS(req, req.ServerResponse, pws) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
p.Logger.Println("error mangling ws:", err) |
|
|
|
iproxy.logger.Println("error mangling ws:", err) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
if mangled { |
|
|
|
if mangled { |
|
|
@ -611,7 +728,7 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
|
|
|
|
|
|
|
|
addWSMessage(req, pws) |
|
|
|
addWSMessage(req, pws) |
|
|
|
if err := saveIfExists(req); err != nil { |
|
|
|
if err := saveIfExists(req); err != nil { |
|
|
|
p.Logger.Println("error saving request:", err) |
|
|
|
iproxy.logger.Println("error saving request:", err) |
|
|
|
continue |
|
|
|
continue |
|
|
|
} |
|
|
|
} |
|
|
|
lc.WriteMessage(pws.Type, pws.Message) |
|
|
|
lc.WriteMessage(pws.Type, pws.Message) |
|
|
@ -625,13 +742,13 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
mtype, msg, err := lc.ReadMessage() |
|
|
|
mtype, msg, err := lc.ReadMessage() |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
rc.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) |
|
|
|
rc.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) |
|
|
|
p.Logger.Println("error with receiving client message:", err) |
|
|
|
iproxy.logger.Println("error with receiving client message:", err) |
|
|
|
wg.Done() |
|
|
|
wg.Done() |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
pws, err := NewProxyWSMessage(mtype, msg, ToServer) |
|
|
|
pws, err := NewProxyWSMessage(mtype, msg, ToServer) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
p.Logger.Println("error creating ws object:", err.Error()) |
|
|
|
iproxy.logger.Println("error creating ws object:", err.Error()) |
|
|
|
continue |
|
|
|
continue |
|
|
|
} |
|
|
|
} |
|
|
|
pws.Timestamp = time.Now() |
|
|
|
pws.Timestamp = time.Now() |
|
|
@ -639,7 +756,7 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
if checkScope(req) { |
|
|
|
if checkScope(req) { |
|
|
|
newMsg, mangled, err := mangleWS(req, req.ServerResponse, pws) |
|
|
|
newMsg, mangled, err := mangleWS(req, req.ServerResponse, pws) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
p.Logger.Println("error mangling ws:", err) |
|
|
|
iproxy.logger.Println("error mangling ws:", err) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
if mangled { |
|
|
|
if mangled { |
|
|
@ -655,18 +772,18 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
|
|
|
|
|
|
|
|
addWSMessage(req, pws) |
|
|
|
addWSMessage(req, pws) |
|
|
|
if err := saveIfExists(req); err != nil { |
|
|
|
if err := saveIfExists(req); err != nil { |
|
|
|
p.Logger.Println("error saving request:", err) |
|
|
|
iproxy.logger.Println("error saving request:", err) |
|
|
|
continue |
|
|
|
continue |
|
|
|
} |
|
|
|
} |
|
|
|
rc.WriteMessage(pws.Type, pws.Message) |
|
|
|
rc.WriteMessage(pws.Type, pws.Message) |
|
|
|
} |
|
|
|
} |
|
|
|
}() |
|
|
|
}() |
|
|
|
wg.Wait() |
|
|
|
wg.Wait() |
|
|
|
p.Logger.Println("Websocket session complete!") |
|
|
|
iproxy.logger.Println("Websocket session complete!") |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
err := req.Submit() |
|
|
|
err := iproxy.SubmitRequest(req) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
http.Error(w, err.Error(), http.StatusInternalServerError) |
|
|
|
http.Error(w, fmt.Sprintf("error submitting request: %s", err.Error()), http.StatusInternalServerError) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
req.EndDatetime = time.Now() |
|
|
|
req.EndDatetime = time.Now() |
|
|
@ -713,10 +830,7 @@ func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
|
|
|
|
|
|
|
|
|
|
func newProxyServer(logger *log.Logger, iproxy *InterceptingProxy) *http.Server { |
|
|
|
func newProxyServer(logger *log.Logger, iproxy *InterceptingProxy) *http.Server { |
|
|
|
server := &http.Server{ |
|
|
|
server := &http.Server{ |
|
|
|
Handler: proxyHandler{ |
|
|
|
Handler: iproxy, |
|
|
|
Logger: logger, |
|
|
|
|
|
|
|
IProxy: iproxy, |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
ErrorLog: logger, |
|
|
|
ErrorLog: logger, |
|
|
|
} |
|
|
|
} |
|
|
|
return server |
|
|
|
return server |
|
|
|