Skip to content

Commit 901fabe

Browse files
Merge pull request #15 from shadowy-pycoder/android
added transparent proxy functionality to android, bumped to v1.10.2
2 parents c9ab954 + 89db9b6 commit 901fabe

File tree

10 files changed

+50
-31
lines changed

10 files changed

+50
-31
lines changed

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
- [tproxy (via MANGLE and IP_TRANSPARENT)](#tproxy-via-mangle-and-ip_transparent)
2424
- [ARP spoofing](#arp-spoofing)
2525
- [UDP support](#udp-support)
26+
- [Android support](#android-support)
2627
- [Traffic sniffing](#traffic-sniffing)
2728
- [JSON format](#json-format)
2829
- [Colored format](#colored-format)
@@ -106,7 +107,7 @@ You can download the binary for your platform from [Releases](https://github.com
106107
Example:
107108

108109
```shell
109-
GOHPTS_RELEASE=v1.10.1; wget -v https://github.com/shadowy-pycoder/go-http-proxy-to-socks/releases/download/$GOHPTS_RELEASE/gohpts-$GOHPTS_RELEASE-linux-amd64.tar.gz -O gohpts && tar xvzf gohpts && mv -f gohpts-$GOHPTS_RELEASE-linux-amd64 gohpts && ./gohpts -h
110+
GOHPTS_RELEASE=v1.10.2; wget -v https://github.com/shadowy-pycoder/go-http-proxy-to-socks/releases/download/$GOHPTS_RELEASE/gohpts-$GOHPTS_RELEASE-linux-amd64.tar.gz -O gohpts && tar xvzf gohpts && mv -f gohpts-$GOHPTS_RELEASE-linux-amd64 gohpts && ./gohpts -h
110111
```
111112

112113
Alternatively, you can install it using `go install` command (requires Go [1.24](https://go.dev/doc/install) or later):
@@ -308,7 +309,7 @@ To learn more about proxy chains visit [Proxychains Github](https://github.com/r
308309
>
309310
> -- _From [Wiki](https://en.wikipedia.org/wiki/Proxy_server)_
310311
311-
This functionality available only on Linux systems and requires additional setup (`iptables`, ip route, etc)
312+
This functionality available only on Linux systems and Android (arm64) and requires additional setup (`iptables`, ip route, etc)
312313
313314
`-T address` flag specifies the address of transparent proxy server (`GoHPTS` will be running without HTTP server).
314315
@@ -560,6 +561,19 @@ sudo ./gohpts -s <socks5 server> -T 8888 -Tu :8989 -M tproxy -sniff -body -auto
560561
561562
5. Check connection on your host machine, the traffic should go through Kali machine.
562563
564+
### Android support
565+
566+
Transparent proxy can be enabled on Android devices (arm64) with root access. You can install [Termux](https://github.com/termux/termux-app) and run `GoHPTS` as a CLI tool there:
567+
568+
```shell
569+
# you need to root your device first
570+
pkg install tsu iproute2
571+
# Android support added in v1.10.2
572+
GOHPTS_RELEASE=v1.10.2; wget -v https://github.com/shadowy-pycoder/go-http-proxy-to-socks/releases/download/$GOHPTS_RELEASE/gohpts-$GOHPTS_RELEASE-android-arm64.tar.gz -O gohpts && tar xvzf gohpts && mv -f gohpts-$GOHPTS_RELEASE-android-arm64 gohpts && ./gohpts -h
573+
# use your phone as router for LAN devices redirecting their traffic to remote socks5 server
574+
sudo ./gohpts -s remote -t 8888 -Tu :8989 -M tproxy -sniff -body -auto -mark 100 -d -arpspoof "fullduplex true;debug false"
575+
```
576+
563577
## Traffic sniffing
564578
565579
[[Back]](#table-of-contents)

cmd/gohpts/cli.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ const (
1616
app string = "gohpts"
1717
addrSOCKS string = "127.0.0.1:1080"
1818
addrHTTP string = "127.0.0.1:8080"
19-
tproxyOS string = "linux"
2019
)
2120

2221
const usagePrefix string = ` _____ _ _ _____ _______ _____
@@ -105,7 +104,7 @@ func root(args []string) error {
105104
return nil
106105
})
107106
daemon := flags.Bool("D", false, "Run as a daemon (provide -logfile to see logs)")
108-
if runtime.GOOS == tproxyOS {
107+
if slices.Contains(gohpts.SupportedTProxyOS, runtime.GOOS) {
109108
flags.StringVar(&conf.TProxy, "t", "", "Address of transparent proxy server (it starts along with HTTP proxy server)")
110109
flags.StringVar(&conf.TProxyOnly, "T", "", "Address of transparent proxy server (no HTTP)")
111110
flags.StringVar(&conf.TProxyUDP, "Tu", "", "Address of transparent UDP proxy server")
@@ -152,7 +151,7 @@ func root(args []string) error {
152151

153152
flags.Usage = func() {
154153
fmt.Print(usagePrefix)
155-
if runtime.GOOS == tproxyOS {
154+
if slices.Contains(gohpts.SupportedTProxyOS, runtime.GOOS) {
156155
fmt.Print(usageTproxy)
157156
}
158157
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/google/uuid v1.6.0
88
github.com/rs/zerolog v1.34.0
99
github.com/shadowy-pycoder/colors v0.0.1
10-
github.com/shadowy-pycoder/mshark v0.0.14
10+
github.com/shadowy-pycoder/mshark v0.0.15
1111
github.com/wzshiming/socks5 v0.5.2
1212
golang.org/x/sys v0.33.0
1313
golang.org/x/term v0.32.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
3434
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
3535
github.com/shadowy-pycoder/colors v0.0.1 h1:weCj/YIOupqy4BSP8KuVzr20fC+cuAv/tArz7bhhkP4=
3636
github.com/shadowy-pycoder/colors v0.0.1/go.mod h1:lkrJS1PY2oVigNLTT6pkbF7B/v0YcU2LD5PZnss1Q4U=
37-
github.com/shadowy-pycoder/mshark v0.0.14 h1:Gou+y9tIEjNSztGWzfFSYJJ8G0DDNYmkvKTQUZDYeVQ=
38-
github.com/shadowy-pycoder/mshark v0.0.14/go.mod h1:FqbHFdsx0zMnrZZH0+oPzaFcleP4O+tUWv8i5gxo87k=
37+
github.com/shadowy-pycoder/mshark v0.0.15 h1:n8UrfCkb7fZHg8Ny/eCFEJwv3cfo23P2+md5LztvdME=
38+
github.com/shadowy-pycoder/mshark v0.0.15/go.mod h1:FqbHFdsx0zMnrZZH0+oPzaFcleP4O+tUWv8i5gxo87k=
3939
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
4040
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
4141
github.com/wzshiming/socks5 v0.5.2 h1:LtoowVNwAmkIQSkP1r1Wg435xUmC+tfRxorNW30KtnM=

gohpts.go

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const (
5252
var (
5353
supportedChainTypes = []string{"strict", "dynamic", "random", "round_robin"}
5454
SupportedTProxyModes = []string{"redirect", "tproxy"}
55+
SupportedTProxyOS = []string{"linux", "android"}
5556
errInvalidWrite = errors.New("invalid write result")
5657
)
5758

@@ -258,16 +259,16 @@ func New(conf *Config) *proxyapp {
258259
sl := snifflogger.Level(lvl)
259260
p.logger = &l
260261
p.snifflogger = &sl
261-
if runtime.GOOS == "linux" && conf.TProxy != "" && conf.TProxyOnly != "" {
262+
if slices.Contains(SupportedTProxyOS, runtime.GOOS) && conf.TProxy != "" && conf.TProxyOnly != "" {
262263
p.logger.Fatal().Msg("Cannot specify TPRoxy and TProxyOnly at the same time")
263-
} else if runtime.GOOS == "linux" && conf.TProxyMode != "" && !slices.Contains(SupportedTProxyModes, conf.TProxyMode) {
264+
} else if slices.Contains(SupportedTProxyOS, runtime.GOOS) && conf.TProxyMode != "" && !slices.Contains(SupportedTProxyModes, conf.TProxyMode) {
264265
p.logger.Fatal().Msg("Incorrect TProxyMode provided")
265-
} else if runtime.GOOS != "linux" && (conf.TProxy != "" || conf.TProxyOnly != "" || conf.TProxyMode != "" || conf.TProxyUDP != "") {
266+
} else if !slices.Contains(SupportedTProxyOS, runtime.GOOS) && (conf.TProxy != "" || conf.TProxyOnly != "" || conf.TProxyMode != "" || conf.TProxyUDP != "") {
266267
conf.TProxy = ""
267268
conf.TProxyOnly = ""
268269
conf.TProxyMode = ""
269270
conf.TProxyUDP = ""
270-
p.logger.Warn().Msgf("[%s] functionality only available on linux systems", conf.TProxyMode)
271+
p.logger.Warn().Msgf("[%s] functionality only available on linux or android systems", conf.TProxyMode)
271272
}
272273
p.tproxyMode = conf.TProxyMode
273274
tproxyonly := conf.TProxyOnly != ""
@@ -301,12 +302,12 @@ func New(conf *Config) *proxyapp {
301302
p.logger.Fatal().Msgf("%s: address already in use", p.tproxyAddrUDP)
302303
}
303304
p.auto = conf.Auto
304-
if p.auto && runtime.GOOS != "linux" {
305-
p.logger.Fatal().Msg("Auto setup is available only on linux systems")
305+
if p.auto && !slices.Contains(SupportedTProxyOS, runtime.GOOS) {
306+
p.logger.Fatal().Msg("Auto setup is available only on linux/android systems")
306307
}
307308
p.mark = conf.Mark
308-
if p.mark > 0 && runtime.GOOS != "linux" {
309-
p.logger.Fatal().Msg("SO_MARK is available only on linux systems")
309+
if p.mark > 0 && !slices.Contains(SupportedTProxyOS, runtime.GOOS) {
310+
p.logger.Fatal().Msg("SO_MARK is available only on linux/android systems")
310311
}
311312
if p.mark > 0xFFFFFFFF {
312313
p.logger.Fatal().Msg("SO_MARK is out of range")
@@ -469,8 +470,8 @@ func New(conf *Config) *proxyapp {
469470
}
470471
}
471472
if conf.ARPSpoof != "" {
472-
if runtime.GOOS != "linux" {
473-
p.logger.Fatal().Msg("ARP spoof setup is available only on linux systems")
473+
if !slices.Contains(SupportedTProxyOS, runtime.GOOS) {
474+
p.logger.Fatal().Msg("ARP spoof setup is available only on linux/android systems")
474475
}
475476
if !p.auto {
476477
p.logger.Warn().Msg("ARP spoof setup requires iptables configuration")
@@ -1508,7 +1509,10 @@ func (p *proxyapp) applyCommonRedirectRules(opts map[string]string) {
15081509
} else {
15091510
iface, err = network.GetDefaultInterface()
15101511
if err != nil {
1511-
p.logger.Fatal().Err(err).Msg("failed getting default network interface")
1512+
iface, err = network.GetDefaultInterfaceFromRoute()
1513+
if err != nil {
1514+
p.logger.Fatal().Err(err).Msg("failed getting default network interface")
1515+
}
15121516
}
15131517
}
15141518
cmdForwardFilter := exec.Command("bash", "-c", fmt.Sprintf(`

tproxy_linux.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//go:build linux
2-
// +build linux
1+
//go:build linux || (android && arm)
2+
// +build linux android,arm
33

44
package gohpts
55

tproxy_nonlinux.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
//go:build !linux
1+
//go:build !linux && !(android && arm)
22
// +build !linux
3+
// +build !android !arm
34

45
package gohpts
56

tproxy_udp_linux.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//go:build linux
2-
// +build linux
1+
//go:build linux || (android && arm)
2+
// +build linux android,arm
33

44
package gohpts
55

@@ -181,14 +181,14 @@ func newTproxyServerUDP(p *proxyapp) *tproxyServerUDP {
181181
} else {
182182
tsu.iface, err = network.GetDefaultInterface()
183183
if err != nil {
184-
tsu.p.logger.Fatal().Err(err).Msgf("[udp %s] Failed getting default interface", tsu.p.tproxyMode)
184+
tsu.iface, err = network.GetDefaultInterfaceFromRoute()
185+
if err != nil {
186+
tsu.p.logger.Fatal().Err(err).Msgf("[udp %s] Failed getting default interface", tsu.p.tproxyMode)
187+
}
185188
}
186189
}
187190
if tsu.p.arpspoofer != nil {
188-
gw, err := network.GetGatewayIPv4FromInterface(tsu.iface.Name)
189-
if err != nil {
190-
tsu.p.logger.Fatal().Err(err).Msgf("[udp %s] failed getting gateway from %s", tsu.p.tproxyMode, tsu.iface.Name)
191-
}
191+
gw := tsu.p.arpspoofer.GatewayIP()
192192
tsu.gwDNS = &net.UDPAddr{IP: net.ParseIP(gw.String()), Port: 53}
193193
lc = net.ListenConfig{
194194
Control: func(network, address string, conn syscall.RawConn) error {

tproxy_udp_nonlinux.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
//go:build !linux
1+
//go:build !linux && !(android && arm)
22
// +build !linux
3+
// +build !android !arm
34

45
package gohpts
56

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.10.1"
3+
const Version string = "gohpts v1.10.2"

0 commit comments

Comments
 (0)