Skip to content

Commit ecb3c1b

Browse files
Merge pull request #5 from shadowy-pycoder/feature
Optional colored output
2 parents fa9cf05 + fc7af7d commit ecb3c1b

File tree

4 files changed

+39
-48
lines changed

4 files changed

+39
-48
lines changed

README.md

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ You can download the binary for your platform from [Releases](https://github.com
9393
Example:
9494

9595
```shell
96-
HPTS_RELEASE=v1.7.0; wget -v https://github.com/shadowy-pycoder/go-http-proxy-to-socks/releases/download/$HPTS_RELEASE/gohpts-$HPTS_RELEASE-linux-amd64.tar.gz -O gohpts && tar xvzf gohpts && mv -f gohpts-$HPTS_RELEASE-linux-amd64 gohpts && ./gohpts -h
96+
HPTS_RELEASE=v1.7.1; wget -v https://github.com/shadowy-pycoder/go-http-proxy-to-socks/releases/download/$HPTS_RELEASE/gohpts-$HPTS_RELEASE-linux-amd64.tar.gz -O gohpts && tar xvzf gohpts && mv -f gohpts-$HPTS_RELEASE-linux-amd64 gohpts && ./gohpts -h
9797
```
9898

9999
Alternatively, you can install it using `go install` command (requires Go [1.24](https://go.dev/doc/install) or later):
@@ -132,36 +132,38 @@ GitHub: https://github.com/shadowy-pycoder/go-http-proxy-to-socks
132132
Usage: gohpts [OPTIONS]
133133
Options:
134134
-h Show this help message and exit.
135-
-D Run as a daemon (provide -logfile to see logs)
135+
-D Run as a daemon (provide -logfile to see logs)
136136
-M value
137-
Transparent proxy mode: [redirect tproxy]
137+
Transparent proxy mode: [redirect tproxy]
138138
-T string
139-
Address of transparent proxy server (no HTTP)
139+
Address of transparent proxy server (no HTTP)
140140
-U string
141-
User for HTTP proxy (basic auth). This flag invokes prompt for password (not echoed to terminal)
141+
User for HTTP proxy (basic auth). This flag invokes prompt for password (not echoed to terminal)
142142
-c string
143-
Path to certificate PEM encoded file
144-
-d Show logs in DEBUG mode
143+
Path to certificate PEM encoded file
144+
-color
145+
Enable colored output for logs in stdout (no effect if log file provided or -j flag specified)
146+
-d Show logs in DEBUG mode
145147
-f string
146-
Path to server configuration file in YAML format
147-
-j Show logs in JSON format
148+
Path to server configuration file in YAML format
149+
-j Show logs in JSON format
148150
-k string
149-
Path to private key PEM encoded file
151+
Path to private key PEM encoded file
150152
-l string
151-
Address of HTTP proxy server (default "127.0.0.1:8080")
153+
Address of HTTP proxy server (default "127.0.0.1:8080")
152154
-logfile string
153-
Log file path (Default: stdout)
155+
Log file path (Default: stdout)
154156
-s string
155-
Address of SOCKS5 proxy server (default "127.0.0.1:1080")
157+
Address of SOCKS5 proxy server (default "127.0.0.1:1080")
156158
-sniff
157-
Enable traffic sniffing for HTTP and TLS
159+
Enable traffic sniffing for HTTP and TLS
158160
-snifflog string
159-
Sniffed traffic log file path (Default: the same as -logfile)
161+
Sniffed traffic log file path (Default: the same as -logfile)
160162
-t string
161-
Address of transparent proxy server (it starts along with HTTP proxy server)
163+
Address of transparent proxy server (it starts along with HTTP proxy server)
162164
-u string
163-
User for SOCKS5 proxy authentication. This flag invokes prompt for password (not echoed to terminal)
164-
-v print version
165+
User for SOCKS5 proxy authentication. This flag invokes prompt for password (not echoed to terminal)
166+
-v print version
165167
```
166168
167169
### Configuration via CLI flags

cmd/gohpts/cli.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ import (
1313

1414
const (
1515
app string = "gohpts"
16-
addrSOCKS = "127.0.0.1:1080"
17-
addrHTTP = "127.0.0.1:8080"
18-
tproxyOS = "linux"
16+
addrSOCKS string = "127.0.0.1:1080"
17+
addrHTTP string = "127.0.0.1:8080"
18+
tproxyOS string = "linux"
1919
)
2020
const usagePrefix string = `
2121
_____ _ _ _____ _______ _____
@@ -61,6 +61,7 @@ func root(args []string) error {
6161
flags.BoolVar(&conf.Json, "j", false, "Show logs in JSON format")
6262
flags.BoolVar(&conf.Sniff, "sniff", false, "Enable traffic sniffing for HTTP and TLS")
6363
flags.StringVar(&conf.SniffLogFile, "snifflog", "", "Sniffed traffic log file path (Default: the same as -logfile)")
64+
flags.BoolVar(&conf.Color, "color", false, "Enable colored output for logs in stdout (no effect if log file provided or -j flag specified)")
6465
flags.BoolFunc("v", "print version", func(flagValue string) error {
6566
fmt.Println(gohpts.Version)
6667
os.Exit(0)

gohpts.go

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ func (p *proxyapp) sniffreporter(wg *sync.WaitGroup, sniffheader *[]string, reqC
532532
defer wg.Done()
533533
sniffheaderlen := len(*sniffheader)
534534
for {
535-
req, okreq := <-reqChan // if resp comes first it blocks
535+
req, okreq := <-reqChan // FIX: if resp comes first it blocks
536536
resp, okresp := <-respChan
537537
if !okreq || !okresp {
538538
return
@@ -543,7 +543,7 @@ func (p *proxyapp) sniffreporter(wg *sync.WaitGroup, sniffheader *[]string, reqC
543543
}
544544
}
545545

546-
func sniff(data []byte, logger *zerolog.Logger) ([]byte, error) {
546+
func sniff(data []byte) ([]byte, error) {
547547
// TODO: check if it is http or tls beforehand
548548
h := &layers.HTTPMessage{}
549549
if err := h.Parse(data); err == nil && !h.IsEmpty() {
@@ -559,26 +559,13 @@ func sniff(data []byte, logger *zerolog.Logger) ([]byte, error) {
559559
if len(m.Records) > 0 {
560560
hsrec := m.Records[0]
561561
if hsrec.ContentType == layers.HandshakeTLSVal { // TODO: add more cases, parse all records
562-
parser := layers.HSTLSParserByType(hsrec.Data[0])
563-
switch parser.(type) {
564-
case *layers.TLSClientHello:
565-
tc := parser.(*layers.TLSClientHello)
566-
err := tc.ParseHS(hsrec.Data)
562+
switch parser := layers.HSTLSParserByType(hsrec.Data[0]).(type) {
563+
case *layers.TLSClientHello, *layers.TLSServerHello:
564+
err := parser.ParseHS(hsrec.Data)
567565
if err != nil {
568566
return nil, err
569567
}
570-
j, err := json.Marshal(tc)
571-
if err != nil {
572-
return nil, err
573-
}
574-
return j, nil
575-
case *layers.TLSServerHello:
576-
ts := parser.(*layers.TLSServerHello)
577-
err := ts.ParseHS(hsrec.Data)
578-
if err != nil {
579-
return nil, err
580-
}
581-
j, err := json.Marshal(ts)
568+
j, err := json.Marshal(parser)
582569
if err != nil {
583570
return nil, err
584571
}
@@ -605,7 +592,7 @@ func (p *proxyapp) copyWithTimeout(dst net.Conn, src net.Conn, msgChan chan<- []
605592
break
606593
}
607594
if p.sniff {
608-
s, err := sniff(buf[0:nr], p.logger)
595+
s, err := sniff(buf[0:nr])
609596
if err == nil {
610597
msgChan <- s
611598
}
@@ -665,7 +652,7 @@ func parseProxyAuth(auth string) (username, password string, ok bool) {
665652
return "", "", false
666653
}
667654
const prefix = "Basic "
668-
if len(auth) < len(prefix) || strings.ToLower(prefix) != strings.ToLower(auth[:len(prefix)]) {
655+
if len(auth) < len(prefix) || !strings.EqualFold(prefix, auth[:len(prefix)]) {
669656
return "", "", false
670657
}
671658
c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
@@ -797,23 +784,24 @@ type Config struct {
797784
Json bool
798785
Sniff bool
799786
SniffLogFile string
787+
Color bool
800788
}
801789

802790
type logWriter struct {
803791
file *os.File
804792
}
805793

806794
func (writer logWriter) Write(bytes []byte) (int, error) {
807-
return fmt.Fprintf(writer.file, fmt.Sprintf("%s | ERROR | %s", time.Now().Format(time.RFC3339), string(bytes)))
795+
return fmt.Fprintf(writer.file, "%s ERR %s", time.Now().Format(time.RFC3339), string(bytes))
808796
}
809797

810798
type jsonLogWriter struct {
811799
file *os.File
812800
}
813801

814802
func (writer jsonLogWriter) Write(bytes []byte) (int, error) {
815-
return fmt.Fprintf(writer.file, fmt.Sprintf("{\"level\":\"error\",\"time\":\"%s\",\"message\":\"%s\"}\n",
816-
time.Now().Format(time.RFC3339), strings.TrimRight(string(bytes), "\n")))
803+
return fmt.Fprintf(writer.file, "{\"level\":\"error\",\"time\":\"%s\",\"message\":\"%s\"}\n",
804+
time.Now().Format(time.RFC3339), strings.TrimRight(string(bytes), "\n"))
817805
}
818806

819807
type proxyEntry struct {
@@ -902,8 +890,8 @@ func New(conf *Config) *proxyapp {
902890
log.SetFlags(0)
903891
logWriter := logWriter{file: logfile}
904892
log.SetOutput(logWriter)
905-
noColor := logfile != os.Stdout
906-
sniffNoColor := snifflog != os.Stdout
893+
noColor := !conf.Color || logfile != os.Stdout
894+
sniffNoColor := !conf.Color || snifflog != os.Stdout
907895
output := zerolog.ConsoleWriter{Out: logfile, TimeFormat: time.RFC3339, NoColor: noColor}
908896
logger = zerolog.New(output).With().Timestamp().Logger()
909897
sniffoutput := zerolog.ConsoleWriter{Out: snifflog, TimeFormat: time.RFC3339, NoColor: sniffNoColor}

version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
package gohpts
22

3-
const Version string = "gohpts v1.7.0"
3+
const Version string = "gohpts v1.7.1"

0 commit comments

Comments
 (0)