@@ -367,33 +367,28 @@ func (p *proxyapp) doReq(w http.ResponseWriter, r *http.Request, sock *http.Clie
367367}
368368
369369func (p * proxyapp ) colorizeStatus (code int , status string , bg bool ) string {
370- if ! p .nocolor {
371- if bg {
372- if code < 300 {
373- status = colors .GreenBg (status ).String ()
374- } else if code < 400 {
375- status = colors .YellowBg (status ).String ()
376- } else {
377- status = colors .RedBgDark (status ).String ()
378- }
370+ if bg {
371+ if code < 300 {
372+ status = colors .GreenBg (status ).String ()
373+ } else if code < 400 {
374+ status = colors .YellowBg (status ).String ()
379375 } else {
380- if code < 300 {
381- status = colors .Green (status ).String ()
382- } else if code < 400 {
383- status = colors .Yellow (status ).String ()
384- } else {
385- status = colors .Red (status ).String ()
386- }
376+ status = colors .RedBgDark (status ).String ()
377+ }
378+ } else {
379+ if code < 300 {
380+ status = colors .Green (status ).String ()
381+ } else if code < 400 {
382+ status = colors .Yellow (status ).String ()
383+ } else {
384+ status = colors .Red (status ).String ()
387385 }
388386 }
389387 return status
390388}
391389
392- func (p * proxyapp ) colorizeHTTP (req * http.Request , resp * http.Response , reqBodySaved , respBodySaved * []byte ) {
393- * respBodySaved = bytes .Trim (* respBodySaved , "\r \n \t " )
394- * reqBodySaved = bytes .Trim (* reqBodySaved , "\r \n \t " )
390+ func (p * proxyapp ) colorizeHTTP (req * http.Request , resp * http.Response , reqBodySaved , respBodySaved * []byte , id uuid.UUID ) string {
395391 var sb strings.Builder
396- id := uuid .New ()
397392 if p .sniffnocolor {
398393 sb .WriteString (fmt .Sprintf ("%s " , colors .WrapBrackets (id .String ())))
399394 sb .WriteString (fmt .Sprintf ("%s %s %s " , req .Method , req .URL , req .Proto ))
@@ -464,12 +459,17 @@ func (p *proxyapp) colorizeHTTP(req *http.Request, resp *http.Response, reqBodyS
464459 }
465460 }
466461 }
467- p .snifflogger .Log ().Msg (sb .String ())
462+ return sb .String ()
463+ }
464+
465+ func (p * proxyapp ) colorizeTLS (req * layers.TLSClientHello , resp * layers.TLSServerHello , id uuid.UUID ) string {
466+ return "TODO:"
468467}
469468
470469func (p * proxyapp ) highlightPatterns (line string ) (string , bool ) {
471470 matched := false
472471
472+ // TODO: make this configurable
473473 // line, matched = p.replace(line, ipPortPattern, colors.YellowBg, matched)
474474 // line, matched = p.replace(line, domainPattern, colors.YellowBg, matched)
475475 line , matched = p .replace (line , jwtPattern , colors .Magenta , matched )
@@ -566,26 +566,29 @@ func (p *proxyapp) handleForward(w http.ResponseWriter, r *http.Request) {
566566 respBodySaved , _ = io .ReadAll (gzr )
567567 }
568568 }
569+ reqBodySaved = bytes .Trim (reqBodySaved , "\r \n \t " )
570+ respBodySaved = bytes .Trim (respBodySaved , "\r \n \t " )
569571 }
570572 if p .json {
571573 sniffheader := make ([]string , 0 , 4 )
572574 j , err := json .Marshal (& layers.HTTPMessage {Request : r })
573575 if err == nil {
574576 sniffheader = append (sniffheader , string (j ))
575- if p .body && len (reqBodySaved ) > 0 {
576- sniffheader = append (sniffheader , fmt .Sprintf ("{\" req_body\" :%q}" , reqBodySaved ))
577- }
578577 }
579578 j , err = json .Marshal (& layers.HTTPMessage {Response : resp })
580579 if err == nil {
581580 sniffheader = append (sniffheader , string (j ))
582- if p .body && len (respBodySaved ) > 0 {
583- sniffheader = append (sniffheader , fmt .Sprintf ("{\" resp_body\" :%q}" , respBodySaved ))
584- }
581+ }
582+ if p .body && len (reqBodySaved ) > 0 {
583+ sniffheader = append (sniffheader , fmt .Sprintf ("{\" req_body\" :%s}" , reqBodySaved ))
584+ }
585+ if p .body && len (respBodySaved ) > 0 {
586+ sniffheader = append (sniffheader , fmt .Sprintf ("{\" resp_body\" :%s}" , respBodySaved ))
585587 }
586588 p .snifflogger .Log ().Msg (fmt .Sprintf ("[%s]" , strings .Join (sniffheader , "," )))
587589 } else {
588- p .colorizeHTTP (req , resp , & reqBodySaved , & respBodySaved )
590+ id := uuid .New ()
591+ p .snifflogger .Log ().Msg (p .colorizeHTTP (req , resp , & reqBodySaved , & respBodySaved , id ))
589592 }
590593 }
591594 defer resp .Body .Close ()
@@ -644,7 +647,11 @@ func (p *proxyapp) handleForward(w http.ResponseWriter, r *http.Request) {
644647 if chunked {
645648 written = fmt .Sprintf ("%s - chunked" , written )
646649 }
647- p .logger .Debug ().Msgf ("%s - %s - %s - %s - %s" , r .Proto , r .Method , r .Host , p .colorizeStatus (resp .StatusCode , resp .Status , false ), written )
650+ status := resp .Status
651+ if ! p .nocolor {
652+ status = p .colorizeStatus (resp .StatusCode , status , false )
653+ }
654+ p .logger .Debug ().Msgf ("%s - %s - %s - %s - %s" , r .Proto , r .Method , r .Host , status , written )
648655 if len (resp .Trailer ) == announcedTrailers {
649656 copyHeader (w .Header (), resp .Trailer )
650657 }
@@ -705,77 +712,162 @@ func (p *proxyapp) handleTunnel(w http.ResponseWriter, r *http.Request) {
705712
706713 p .logger .Debug ().Msgf ("%s - %s - %s" , r .Proto , r .Method , r .Host )
707714 p .logger .Debug ().Msgf ("src: %s - dst: %s" , srcConnStr , dstConnStr )
708- reqChan := make (chan [] byte )
709- respChan := make (chan [] byte )
715+ reqChan := make (chan layers. Layer )
716+ respChan := make (chan layers. Layer )
710717 var wg sync.WaitGroup
711718 wg .Add (2 )
712719 go p .transfer (& wg , dstConn , srcConn , dstConnStr , srcConnStr , reqChan )
713720 go p .transfer (& wg , srcConn , dstConn , srcConnStr , dstConnStr , respChan )
714721 if p .sniff {
715722 wg .Add (1 )
716- sniffheader := make ([]string , 0 , 4 )
717- if p .sniffnocolor {
718- sniffheader = append (sniffheader , fmt .Sprintf ("{\" connection\" :{\" src_local\" :%q,\" src_remote\" :%q,\" dst_local\" :%q,\" dst_remote\" :%q}}" ,
723+ sniffheader := make ([]string , 0 , 6 )
724+ id := uuid .New ()
725+ if p .json {
726+ sniffheader = append (sniffheader , fmt .Sprintf ("{\" connection\" :{\" src_local\" :%s,\" src_remote\" :%s,\" dst_local\" :%s,\" dst_remote\" :%s}}" ,
719727 srcConn .LocalAddr (), srcConn .RemoteAddr (), dstConn .LocalAddr (), dstConn .RemoteAddr ()))
720728 j , err := json .Marshal (& layers.HTTPMessage {Request : r })
721729 if err == nil {
722730 sniffheader = append (sniffheader , string (j ))
723731 }
732+ } else {
733+ // TODO:
724734 }
725- go p .sniffreporter (& wg , & sniffheader , reqChan , respChan )
735+ go p .sniffreporter (& wg , & sniffheader , reqChan , respChan , id )
726736 }
727737 wg .Wait ()
728738}
729739
730- func (p * proxyapp ) sniffreporter (wg * sync.WaitGroup , sniffheader * []string , reqChan <- chan []byte , respChan <- chan []byte ) {
740+ func (p * proxyapp ) colorizeReqResp (req , resp layers.Layer , sniffheader * []string , id uuid.UUID ) error {
741+ switch reqt := req .(type ) {
742+ case * layers.HTTPMessage :
743+ var reqBodySaved , respBodySaved []byte
744+ rest := resp .(* layers.HTTPMessage )
745+ if p .body {
746+ reqBodySaved , _ = io .ReadAll (reqt .Request .Body )
747+ respBodySaved , _ = io .ReadAll (rest .Response .Body )
748+ reqBodySaved = bytes .Trim (reqBodySaved , "\r \n \t " )
749+ respBodySaved = bytes .Trim (respBodySaved , "\r \n \t " )
750+ }
751+ if p .json {
752+ j1 , err := json .Marshal (reqt )
753+ if err != nil {
754+ return err
755+ }
756+ j2 , err := json .Marshal (rest )
757+ if err != nil {
758+ return err
759+ }
760+ * sniffheader = append (* sniffheader , string (j1 ), string (j2 ))
761+ if p .body && len (reqBodySaved ) > 0 {
762+ * sniffheader = append (* sniffheader , fmt .Sprintf ("{\" req_body\" :%s}" , reqBodySaved ))
763+ }
764+ if p .body && len (respBodySaved ) > 0 {
765+ * sniffheader = append (* sniffheader , fmt .Sprintf ("{\" resp_body\" :%s}" , respBodySaved ))
766+ }
767+ } else {
768+ * sniffheader = append (* sniffheader , p .colorizeHTTP (reqt .Request , rest .Response , & reqBodySaved , & respBodySaved , id ))
769+ }
770+ case * layers.TLSMessage :
771+ var chs * layers.TLSClientHello
772+ var shs * layers.TLSServerHello
773+ if len (reqt .Records ) > 0 {
774+ hsrec := reqt .Records [0 ]
775+ if hsrec .ContentType == layers .HandshakeTLSVal { // TODO: add more cases, parse all records
776+ switch parser := layers .HSTLSParserByType (hsrec .Data [0 ]).(type ) {
777+ case * layers.TLSClientHello :
778+ err := parser .ParseHS (hsrec .Data )
779+ if err != nil {
780+ return err
781+ }
782+ chs = parser
783+ }
784+ }
785+ }
786+ rest := resp .(* layers.TLSMessage )
787+ if len (rest .Records ) > 0 {
788+ hsrec := rest .Records [0 ]
789+ if hsrec .ContentType == layers .HandshakeTLSVal {
790+ switch parser := layers .HSTLSParserByType (hsrec .Data [0 ]).(type ) {
791+ case * layers.TLSServerHello :
792+ err := parser .ParseHS (hsrec .Data )
793+ if err != nil {
794+ return err
795+ }
796+ shs = parser
797+ }
798+ }
799+ }
800+ if chs != nil && shs != nil {
801+ if p .json {
802+ j1 , err := json .Marshal (chs )
803+ if err != nil {
804+ return err
805+ }
806+ j2 , err := json .Marshal (shs )
807+ if err != nil {
808+ return err
809+ }
810+ * sniffheader = append (* sniffheader , string (j1 ), string (j2 ))
811+ } else {
812+ * sniffheader = append (* sniffheader , p .colorizeTLS (chs , shs , id ))
813+ }
814+ }
815+ }
816+ return nil
817+ }
818+
819+ func (p * proxyapp ) sniffreporter (wg * sync.WaitGroup , sniffheader * []string , reqChan , respChan <- chan layers.Layer , id uuid.UUID ) {
731820 defer wg .Done ()
732821 sniffheaderlen := len (* sniffheader )
822+ var reqQueue , respQueue []layers.Layer
733823 for {
734- req , okreq := <- reqChan // FIX: if resp comes first it blocks
735- resp , okresp := <- respChan
736- if ! okreq || ! okresp {
737- return
824+ select {
825+ case req , ok := <- reqChan :
826+ if ! ok {
827+ return
828+ } else {
829+ reqQueue = append (reqQueue , req )
830+ }
831+ case resp , ok := <- respChan :
832+ if ! ok {
833+ return
834+ } else if len (reqQueue ) > 0 { // HACK: is this right?
835+ respQueue = append (respQueue , resp )
836+ }
837+ }
838+ if len (reqQueue ) > 0 && len (respQueue ) > 0 {
839+ req := reqQueue [0 ]
840+ resp := respQueue [0 ]
841+ reqQueue = reqQueue [1 :]
842+ respQueue = respQueue [1 :]
843+
844+ err := p .colorizeReqResp (req , resp , sniffheader , id )
845+ if err == nil {
846+ if p .json {
847+ p .snifflogger .Log ().Msg (fmt .Sprintf ("[%s]" , strings .Join (* sniffheader , "," )))
848+ } else {
849+ p .snifflogger .Log ().Msg (fmt .Sprintf ("%s" , strings .Join (* sniffheader , "\n " )))
850+ }
851+ }
852+ * sniffheader = (* sniffheader )[:sniffheaderlen ]
738853 }
739- * sniffheader = append (* sniffheader , string (req ), string (resp ))
740- p .snifflogger .Debug ().Msg (fmt .Sprintf ("[%s]" , strings .Join (* sniffheader , "," )))
741- * sniffheader = (* sniffheader )[:sniffheaderlen ]
742854 }
743855}
744856
745- func sniff (data []byte , nocolor bool ) ([] byte , error ) {
857+ func dispatch (data []byte ) (layers. Layer , error ) {
746858 // TODO: check if it is http or tls beforehand
747859 h := & layers.HTTPMessage {}
748860 if err := h .Parse (data ); err == nil && ! h .IsEmpty () {
749- j , err := json .Marshal (h )
750- if err == nil {
751- return j , nil
752- }
861+ return h , nil
753862 }
754863 m := & layers.TLSMessage {}
755- if err := m .Parse (data ); err != nil {
756- return nil , err
757- }
758- if len (m .Records ) > 0 {
759- hsrec := m .Records [0 ]
760- if hsrec .ContentType == layers .HandshakeTLSVal { // TODO: add more cases, parse all records
761- switch parser := layers .HSTLSParserByType (hsrec .Data [0 ]).(type ) {
762- case * layers.TLSClientHello , * layers.TLSServerHello :
763- err := parser .ParseHS (hsrec .Data )
764- if err != nil {
765- return nil , err
766- }
767- j , err := json .Marshal (parser )
768- if err != nil {
769- return nil , err
770- }
771- return j , nil
772- }
773- }
864+ if err := m .Parse (data ); err == nil {
865+ return m , nil
774866 }
775867 return nil , fmt .Errorf ("failed sniffing traffic" )
776868}
777869
778- func (p * proxyapp ) copyWithTimeout (dst net.Conn , src net.Conn , msgChan chan <- [] byte ) (written int64 , err error ) {
870+ func (p * proxyapp ) copyWithTimeout (dst net.Conn , src net.Conn , msgChan chan <- layers. Layer ) (written int64 , err error ) {
779871 buf := make ([]byte , 32 * 1024 )
780872 for {
781873 er := src .SetReadDeadline (time .Now ().Add (readTimeout ))
@@ -791,9 +883,9 @@ func (p *proxyapp) copyWithTimeout(dst net.Conn, src net.Conn, msgChan chan<- []
791883 break
792884 }
793885 if p .sniff {
794- s , err := sniff (buf [0 :nr ], p . sniffnocolor )
886+ l , err := dispatch (buf [0 :nr ])
795887 if err == nil {
796- msgChan <- s
888+ msgChan <- l
797889 }
798890 }
799891 nw , ew := dst .Write (buf [0 :nr ])
@@ -828,7 +920,7 @@ func (p *proxyapp) copyWithTimeout(dst net.Conn, src net.Conn, msgChan chan<- []
828920 return written , err
829921}
830922
831- func (p * proxyapp ) transfer (wg * sync.WaitGroup , dst net.Conn , src net.Conn , destName , srcName string , msgChan chan <- [] byte ) {
923+ func (p * proxyapp ) transfer (wg * sync.WaitGroup , dst net.Conn , src net.Conn , destName , srcName string , msgChan chan <- layers. Layer ) {
832924 defer func () {
833925 wg .Done ()
834926 close (msgChan )
0 commit comments