Skip to content

Commit a8d3477

Browse files
made linter happy
1 parent b29119d commit a8d3477

File tree

3 files changed

+125
-58
lines changed

3 files changed

+125
-58
lines changed

cmd/gohpts/cli.go

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,32 @@ const (
1717
addrHTTP string = "127.0.0.1:8080"
1818
tproxyOS string = "linux"
1919
)
20-
const usagePrefix string = ` _____ _ _ _____ _______ _____
20+
21+
const usagePrefix string = ` _____ _ _ _____ _______ _____
2122
/ ____| | | | | __ \__ __/ ____|
22-
| | __ ___ | |__| | |__) | | | | (___
23-
| | |_ |/ _ \| __ | ___/ | | \___ \
23+
| | __ ___ | |__| | |__) | | | | (___
24+
| | |_ |/ _ \| __ | ___/ | | \___ \
2425
| |__| | (_) | | | | | | | ____) |
25-
\_____|\___/|_| |_|_| |_| |_____/
26-
27-
GoHPTS (HTTP(S) Proxy to SOCKS5 proxy) by shadowy-pycoder
26+
\_____|\___/|_| |_|_| |_| |_____/
27+
28+
GoHPTS (HTTP(S) Proxy to SOCKS5 proxy) by shadowy-pycoder
2829
GitHub: https://github.com/shadowy-pycoder/go-http-proxy-to-socks
2930
30-
Usage: gohpts [OPTIONS]
31+
Usage: gohpts [OPTIONS]
3132
Options:
3233
-h Show this help message and exit
3334
-v Show version and build information
3435
-D Run as a daemon (provide -logfile to see logs)
3536
3637
Proxy:
37-
-l Address of HTTP proxy server (default "127.0.0.1:8080")
38+
-l Address of HTTP proxy server (default "127.0.0.1:8080")
3839
-s Address of SOCKS5 proxy server (default "127.0.0.1:1080")
3940
-c Path to certificate PEM encoded file
4041
-k Path to private key PEM encoded file
4142
-U User for HTTP proxy (basic auth). This flag invokes prompt for password (not echoed to terminal)
4243
-u User for SOCKS5 proxy authentication. This flag invokes prompt for password (not echoed to terminal)
4344
-f Path to server configuration file in YAML format (overrides other proxy flags)
44-
45+
4546
Logs:
4647
-d Show logs in DEBUG mode
4748
-j Show logs in JSON format
@@ -53,6 +54,7 @@ Options:
5354
-snifflog Sniffed traffic log file path (Default: the same as -logfile)
5455
-body Collect request and response body for HTTP traffic (credentials, tokens, etc)
5556
`
57+
5658
const usageTproxy string = `
5759
TProxy:
5860
-t Address of transparent proxy server (it starts along with HTTP proxy server)
@@ -66,12 +68,27 @@ func root(args []string) error {
6668
conf := gohpts.Config{}
6769
flags := flag.NewFlagSet(app, flag.ExitOnError)
6870
flags.StringVar(&conf.AddrSOCKS, "s", addrSOCKS, "Address of SOCKS5 proxy server")
69-
flags.StringVar(&conf.User, "u", "", "User for SOCKS5 proxy authentication. This flag invokes prompt for password (not echoed to terminal)")
71+
flags.StringVar(
72+
&conf.User,
73+
"u",
74+
"",
75+
"User for SOCKS5 proxy authentication. This flag invokes prompt for password (not echoed to terminal)",
76+
)
7077
flags.StringVar(&conf.AddrHTTP, "l", addrHTTP, "Address of HTTP proxy server")
71-
flags.StringVar(&conf.ServerUser, "U", "", "User for HTTP proxy (basic auth). This flag invokes prompt for password (not echoed to terminal)")
78+
flags.StringVar(
79+
&conf.ServerUser,
80+
"U",
81+
"",
82+
"User for HTTP proxy (basic auth). This flag invokes prompt for password (not echoed to terminal)",
83+
)
7284
flags.StringVar(&conf.CertFile, "c", "", "Path to certificate PEM encoded file")
7385
flags.StringVar(&conf.KeyFile, "k", "", "Path to private key PEM encoded file")
74-
flags.StringVar(&conf.ServerConfPath, "f", "", "Path to server configuration file in YAML format (overrides other proxy flags)")
86+
flags.StringVar(
87+
&conf.ServerConfPath,
88+
"f",
89+
"",
90+
"Path to server configuration file in YAML format (overrides other proxy flags)",
91+
)
7592
daemon := flags.Bool("D", false, "Run as a daemon (provide -logfile to see logs)")
7693
if runtime.GOOS == tproxyOS {
7794
flags.StringVar(&conf.TProxy, "t", "", "Address of transparent proxy server (it starts along with HTTP proxy server)")
@@ -84,12 +101,22 @@ func root(args []string) error {
84101
conf.TProxyMode = flagValue
85102
return nil
86103
})
87-
flags.BoolVar(&conf.Auto, "auto", false, "Automatically setup iptables for transparent proxy (requires elevated privileges)")
88-
flags.UintVar(&conf.Mark, "mark", 0, "Set mark for each packet sent through transparent proxy (Default: redirect 0, tproxy 100)")
104+
flags.BoolVar(
105+
&conf.Auto,
106+
"auto",
107+
false,
108+
"Automatically setup iptables for transparent proxy (requires elevated privileges)",
109+
)
110+
flags.UintVar(
111+
&conf.Mark,
112+
"mark",
113+
0,
114+
"Set mark for each packet sent through transparent proxy (Default: redirect 0, tproxy 100)",
115+
)
89116
}
90117
flags.StringVar(&conf.LogFilePath, "logfile", "", "Log file path (Default: stdout)")
91118
flags.BoolVar(&conf.Debug, "d", false, "Show logs in DEBUG mode")
92-
flags.BoolVar(&conf.Json, "j", false, "Show logs in JSON format")
119+
flags.BoolVar(&conf.JSON, "j", false, "Show logs in JSON format")
93120
flags.BoolVar(&conf.Sniff, "sniff", false, "Enable traffic sniffing for HTTP and TLS")
94121
flags.StringVar(&conf.SniffLogFile, "snifflog", "", "Sniffed traffic log file path (Default: the same as -logfile)")
95122
flags.BoolVar(&conf.NoColor, "nocolor", false, "Disable colored output for logs (no effect if -j flag specified)")

gohpts.go

Lines changed: 61 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Package gohpts transform SOCKS5 proxy into HTTP(S) proxy with support for Transparent Proxy (Redirect and TProxy), Proxychains and Traffic Sniffing
12
package gohpts
23

34
import (
@@ -52,11 +53,19 @@ var (
5253
supportedChainTypes = []string{"strict", "dynamic", "random", "round_robin"}
5354
SupportedTProxyModes = []string{"redirect", "tproxy"}
5455
errInvalidWrite = errors.New("invalid write result")
55-
ipPortPattern = regexp.MustCompile(`\b(?:\d{1,3}\.){3}\d{1,3}(?::(6553[0-5]|655[0-2]\d|65[0-4]\d{2}|6[0-4]\d{3}|[1-5]?\d{1,4}))?\b`)
56-
domainPattern = regexp.MustCompile(`\b(?:[a-zA-Z0-9-]{1,63}\.)+(?:com|net|org|io|co|uk|ru|de|edu|gov|info|biz|dev|app|ai)(?::(6553[0-5]|655[0-2]\d|65[0-4]\d{2}|6[0-4]\d{3}|[1-5]?\d{1,4}))?\b`)
57-
jwtPattern = regexp.MustCompile(`\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b`)
58-
authPattern = regexp.MustCompile(`(?i)(?:"|')?(authorization|auth[_-]?token|access[_-]?token|api[_-]?key|secret|token)(?:"|')?\s*[:=]\s*(?:"|')?([^\s"'&]+)`)
59-
credsPattern = regexp.MustCompile(`(?i)(?:"|')?(username|user|login|email|password|pass|pwd)(?:"|')?\s*[:=]\s*(?:"|')?([^\s"'&]+)`)
56+
ipPortPattern = regexp.MustCompile(
57+
`\b(?:\d{1,3}\.){3}\d{1,3}(?::(6553[0-5]|655[0-2]\d|65[0-4]\d{2}|6[0-4]\d{3}|[1-5]?\d{1,4}))?\b`,
58+
)
59+
domainPattern = regexp.MustCompile(
60+
`\b(?:[a-zA-Z0-9-]{1,63}\.)+(?:com|net|org|io|co|uk|ru|de|edu|gov|info|biz|dev|app|ai)(?::(6553[0-5]|655[0-2]\d|65[0-4]\d{2}|6[0-4]\d{3}|[1-5]?\d{1,4}))?\b`,
61+
)
62+
jwtPattern = regexp.MustCompile(`\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b`)
63+
authPattern = regexp.MustCompile(
64+
`(?i)(?:"|')?(authorization|auth[_-]?token|access[_-]?token|api[_-]?key|secret|token)(?:"|')?\s*[:=]\s*(?:"|')?([^\s"'&]+)`,
65+
)
66+
credsPattern = regexp.MustCompile(
67+
`(?i)(?:"|')?(username|user|login|email|password|pass|pwd)(?:"|')?\s*[:=]\s*(?:"|')?([^\s"'&]+)`,
68+
)
6069
)
6170

6271
// Hop-by-hop headers
@@ -90,7 +99,7 @@ type Config struct {
9099
Mark uint
91100
LogFilePath string
92101
Debug bool
93-
Json bool
102+
JSON bool
94103
Sniff bool
95104
SniffLogFile string
96105
NoColor bool
@@ -152,12 +161,12 @@ func randColor() func(string) *colors.Color {
152161
return rColors[randIndex]
153162
}
154163

155-
func (p *proxyapp) getId() string {
164+
func (p *proxyapp) getID() string {
156165
id := uuid.New()
157166
if p.nocolor {
158-
return fmt.Sprintf("%s", colors.WrapBrackets(id.String()))
167+
return colors.WrapBrackets(id.String())
159168
}
160-
return randColor()(fmt.Sprintf("%s", colors.WrapBrackets(id.String()))).String()
169+
return randColor()(colors.WrapBrackets(id.String())).String()
161170
}
162171

163172
func (p *proxyapp) colorizeStatus(code int, status string, bg bool) string {
@@ -181,7 +190,13 @@ func (p *proxyapp) colorizeStatus(code int, status string, bg bool) string {
181190
return status
182191
}
183192

184-
func (p *proxyapp) colorizeHTTP(req *http.Request, resp *http.Response, reqBodySaved, respBodySaved *[]byte, id string, ts bool) string {
193+
func (p *proxyapp) colorizeHTTP(
194+
req *http.Request,
195+
resp *http.Response,
196+
reqBodySaved, respBodySaved *[]byte,
197+
id string,
198+
ts bool,
199+
) string {
185200
var sb strings.Builder
186201
if ts {
187202
sb.WriteString(fmt.Sprintf("%s ", p.colorizeTimestamp()))
@@ -190,7 +205,7 @@ func (p *proxyapp) colorizeHTTP(req *http.Request, resp *http.Response, reqBodyS
190205
sb.WriteString(id)
191206
sb.WriteString(fmt.Sprintf(" %s %s %s ", req.Method, req.URL, req.Proto))
192207
if req.UserAgent() != "" {
193-
sb.WriteString(fmt.Sprintf("%s", colors.WrapBrackets(req.UserAgent())))
208+
sb.WriteString(colors.WrapBrackets(req.UserAgent()))
194209
}
195210
if req.ContentLength > 0 {
196211
sb.WriteString(fmt.Sprintf(" Len: %d", req.ContentLength))
@@ -224,7 +239,7 @@ func (p *proxyapp) colorizeHTTP(req *http.Request, resp *http.Response, reqBodyS
224239
sb.WriteString(colors.YellowBg(fmt.Sprintf("%s ", req.URL)).String())
225240
sb.WriteString(colors.BlueBg(fmt.Sprintf("%s ", req.Proto)).String())
226241
if req.UserAgent() != "" {
227-
sb.WriteString(colors.Gray(fmt.Sprintf("%s", colors.WrapBrackets(req.UserAgent()))).String())
242+
sb.WriteString(colors.Gray(colors.WrapBrackets(req.UserAgent())).String())
228243
}
229244
if req.ContentLength > 0 {
230245
sb.WriteString(colors.BeigeBg(fmt.Sprintf(" Len: %d", req.ContentLength)).String())
@@ -814,7 +829,7 @@ func (p *proxyapp) handleForward(w http.ResponseWriter, r *http.Request) {
814829
}
815830
p.snifflogger.Log().Msg(fmt.Sprintf("[%s]", strings.Join(sniffheader, ",")))
816831
} else {
817-
id := p.getId()
832+
id := p.getID()
818833
p.snifflogger.Log().Msg(p.colorizeHTTP(req, resp, &reqBodySaved, &respBodySaved, id, false))
819834
}
820835
}
@@ -943,10 +958,13 @@ func (p *proxyapp) handleTunnel(w http.ResponseWriter, r *http.Request) {
943958
if p.sniff {
944959
wg.Add(1)
945960
sniffheader := make([]string, 0, 6)
946-
id := p.getId()
961+
id := p.getID()
947962
if p.json {
948-
sniffheader = append(sniffheader, fmt.Sprintf("{\"connection\":{\"src_remote\":%s,\"src_local\":%s,\"dst_local\":%s,\"dst_remote\":%s}}",
949-
srcConn.RemoteAddr(), srcConn.LocalAddr(), dstConn.LocalAddr(), dstConn.RemoteAddr()))
963+
sniffheader = append(
964+
sniffheader,
965+
fmt.Sprintf("{\"connection\":{\"src_remote\":%s,\"src_local\":%s,\"dst_local\":%s,\"dst_remote\":%s}}",
966+
srcConn.RemoteAddr(), srcConn.LocalAddr(), dstConn.LocalAddr(), dstConn.RemoteAddr()),
967+
)
950968
j, err := json.Marshal(&layers.HTTPMessage{Request: r})
951969
if err == nil {
952970
sniffheader = append(sniffheader, string(j))
@@ -1009,7 +1027,7 @@ func (p *proxyapp) sniffreporter(wg *sync.WaitGroup, sniffheader *[]string, reqC
10091027
if p.json {
10101028
p.snifflogger.Log().Msg(fmt.Sprintf("[%s]", strings.Join(*sniffheader, ",")))
10111029
} else {
1012-
p.snifflogger.Log().Msg(fmt.Sprintf("%s", strings.Join(*sniffheader, "\n")))
1030+
p.snifflogger.Log().Msg(strings.Join(*sniffheader, "\n"))
10131031
}
10141032
}
10151033
*sniffheader = (*sniffheader)[:sniffheaderlen]
@@ -1089,7 +1107,13 @@ readLoop:
10891107
return written, err
10901108
}
10911109

1092-
func (p *proxyapp) transfer(wg *sync.WaitGroup, dst net.Conn, src net.Conn, destName, srcName string, msgChan chan<- layers.Layer) {
1110+
func (p *proxyapp) transfer(
1111+
wg *sync.WaitGroup,
1112+
dst net.Conn,
1113+
src net.Conn,
1114+
destName, srcName string,
1115+
msgChan chan<- layers.Layer,
1116+
) {
10931117
defer func() {
10941118
wg.Done()
10951119
close(msgChan)
@@ -1173,10 +1197,10 @@ func (p *proxyapp) applyRedirectRules() string {
11731197
}
11741198
cmdInit := exec.Command("bash", "-c", `
11751199
set -ex
1176-
iptables -t nat -N GOHPTS 2>/dev/null
1177-
iptables -t nat -F GOHPTS
1178-
1179-
iptables -t nat -A GOHPTS -d 127.0.0.0/8 -j RETURN
1200+
iptables -t nat -N GOHPTS 2>/dev/null
1201+
iptables -t nat -F GOHPTS
1202+
1203+
iptables -t nat -A GOHPTS -d 127.0.0.0/8 -j RETURN
11801204
iptables -t nat -A GOHPTS -p tcp --dport 22 -j RETURN
11811205
`)
11821206
cmdInit.Stdout = os.Stdout
@@ -1186,13 +1210,13 @@ func (p *proxyapp) applyRedirectRules() string {
11861210
}
11871211
if p.httpServerAddr != "" {
11881212
_, httpPort, _ := net.SplitHostPort(p.httpServerAddr)
1189-
cmdHttp := exec.Command("bash", "-c", fmt.Sprintf(`
1213+
cmdHTTP := exec.Command("bash", "-c", fmt.Sprintf(`
11901214
set -ex
11911215
iptables -t nat -A GOHPTS -p tcp --dport %s -j RETURN
11921216
`, httpPort))
1193-
cmdHttp.Stdout = os.Stdout
1194-
cmdHttp.Stderr = os.Stderr
1195-
if err := cmdHttp.Run(); err != nil {
1217+
cmdHTTP.Stdout = os.Stdout
1218+
cmdHTTP.Stderr = os.Stderr
1219+
if err := cmdHTTP.Run(); err != nil {
11961220
p.logger.Fatal().Err(err).Msg("Failed while configuring iptables. Are you root?")
11971221
}
11981222
}
@@ -1241,7 +1265,7 @@ func (p *proxyapp) applyRedirectRules() string {
12411265
for subnet in $(docker network inspect $(docker network ls -q) --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'); do
12421266
iptables -t nat -A GOHPTS -d "$subnet" -j RETURN
12431267
done
1244-
fi
1268+
fi
12451269
12461270
iptables -t nat -A GOHPTS -p tcp -j REDIRECT --to-ports %s
12471271
@@ -1514,7 +1538,7 @@ func getFullAddress(v string, all bool) (string, error) {
15141538
if v == "" {
15151539
return "", nil
15161540
}
1517-
var ip string = "127.0.0.1"
1541+
ip := "127.0.0.1"
15181542
if all {
15191543
ip = "0.0.0.0"
15201544
}
@@ -1549,30 +1573,30 @@ func expandPath(p string) string {
15491573
func New(conf *Config) *proxyapp {
15501574
var logger, snifflogger zerolog.Logger
15511575
var p proxyapp
1552-
var logfile *os.File = os.Stdout
1576+
logfile := os.Stdout
15531577
var snifflog *os.File
15541578
var err error
15551579
p.sniff = conf.Sniff
15561580
p.body = conf.Body
1557-
p.json = conf.Json
1581+
p.json = conf.JSON
15581582
if conf.LogFilePath != "" {
1559-
f, err := os.OpenFile(conf.LogFilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
1583+
f, err := os.OpenFile(conf.LogFilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644)
15601584
if err != nil {
15611585
log.Fatalf("Failed to open log file: %v", err)
15621586
}
15631587
logfile = f
15641588
}
15651589
if conf.SniffLogFile != "" && conf.SniffLogFile != conf.LogFilePath {
1566-
f, err := os.OpenFile(conf.SniffLogFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
1590+
f, err := os.OpenFile(conf.SniffLogFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644)
15671591
if err != nil {
15681592
log.Fatalf("Failed to open sniff log file: %v", err)
15691593
}
15701594
snifflog = f
15711595
} else {
15721596
snifflog = logfile
15731597
}
1574-
p.nocolor = conf.Json || conf.NoColor
1575-
if conf.Json {
1598+
p.nocolor = conf.JSON || conf.NoColor
1599+
if conf.JSON {
15761600
log.SetFlags(0)
15771601
jsonWriter := jsonLogWriter{file: logfile}
15781602
log.SetOutput(jsonWriter)
@@ -1597,7 +1621,7 @@ func New(conf *Config) *proxyapp {
15971621
}
15981622
s := i.(string)
15991623
if p.nocolor {
1600-
return fmt.Sprintf("%s", s)
1624+
return s
16011625
}
16021626
result := ipPortPattern.ReplaceAllStringFunc(s, func(match string) string {
16031627
return colors.Gray(match).String()
@@ -1615,7 +1639,7 @@ func New(conf *Config) *proxyapp {
16151639
output.FormatErrFieldValue = func(i any) string {
16161640
s := i.(string)
16171641
if p.nocolor {
1618-
return fmt.Sprintf("%s", s)
1642+
return s
16191643
}
16201644
result := ipPortPattern.ReplaceAllStringFunc(s, func(match string) string {
16211645
return colors.Red(match).String()
@@ -1624,7 +1648,6 @@ func New(conf *Config) *proxyapp {
16241648
return colors.Red(match).String()
16251649
})
16261650
return result
1627-
16281651
}
16291652
logger = zerolog.New(output).With().Timestamp().Logger()
16301653
sniffoutput := zerolog.ConsoleWriter{Out: snifflog, TimeFormat: time.RFC3339, NoColor: p.nocolor, PartsExclude: []string{"level"}}
@@ -1648,7 +1671,7 @@ func New(conf *Config) *proxyapp {
16481671
sniffoutput.FormatErrFieldValue = func(i any) string {
16491672
s := i.(string)
16501673
if p.nocolor {
1651-
return fmt.Sprintf("%s", s)
1674+
return s
16521675
}
16531676
result := ipPortPattern.ReplaceAllStringFunc(s, func(match string) string {
16541677
return colors.Red(match).String()
@@ -1657,7 +1680,6 @@ func New(conf *Config) *proxyapp {
16571680
return colors.Red(match).String()
16581681
})
16591682
return result
1660-
16611683
}
16621684
snifflogger = zerolog.New(sniffoutput).With().Timestamp().Logger()
16631685
}

0 commit comments

Comments
 (0)