masktunnel 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- masktunnel-0.1.0/MANIFEST.in +18 -0
- masktunnel-0.1.0/PKG-INFO +38 -0
- masktunnel-0.1.0/README.md +11 -0
- masktunnel-0.1.0/go.mod +46 -0
- masktunnel-0.1.0/go.sum +116 -0
- masktunnel-0.1.0/masktunnel/__init__.py +11 -0
- masktunnel-0.1.0/masktunnel/_server.py +86 -0
- masktunnel-0.1.0/masktunnel/_utils.py +15 -0
- masktunnel-0.1.0/masktunnel.egg-info/PKG-INFO +38 -0
- masktunnel-0.1.0/masktunnel.egg-info/SOURCES.txt +27 -0
- masktunnel-0.1.0/masktunnel.egg-info/dependency_links.txt +1 -0
- masktunnel-0.1.0/masktunnel.egg-info/not-zip-safe +1 -0
- masktunnel-0.1.0/masktunnel.egg-info/requires.txt +7 -0
- masktunnel-0.1.0/masktunnel.egg-info/top_level.txt +2 -0
- masktunnel-0.1.0/masktunnel_go/_python.go +81 -0
- masktunnel-0.1.0/masktunnel_go/basic.go +77 -0
- masktunnel-0.1.0/masktunnel_go/bindings.go +136 -0
- masktunnel-0.1.0/masktunnel_go/config.go +15 -0
- masktunnel-0.1.0/masktunnel_go/encoding.go +154 -0
- masktunnel-0.1.0/masktunnel_go/generator.go +172 -0
- masktunnel-0.1.0/masktunnel_go/manager.go +168 -0
- masktunnel-0.1.0/masktunnel_go/mitm.go +663 -0
- masktunnel-0.1.0/masktunnel_go/payload.go +162 -0
- masktunnel-0.1.0/masktunnel_go/python.go +80 -0
- masktunnel-0.1.0/masktunnel_go/server.go +438 -0
- masktunnel-0.1.0/masktunnel_go/ua_parser.go +217 -0
- masktunnel-0.1.0/setup.cfg +4 -0
- masktunnel-0.1.0/setup.py +641 -0
- masktunnel-0.1.0/tests/test_server.py +114 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Include Go source files in masktunnel_go directory
|
|
2
|
+
recursive-include masktunnel_go *.go
|
|
3
|
+
include go.mod
|
|
4
|
+
include go.sum
|
|
5
|
+
|
|
6
|
+
# Include documentation
|
|
7
|
+
include README.md
|
|
8
|
+
|
|
9
|
+
# Exclude unnecessary files
|
|
10
|
+
global-exclude __pycache__
|
|
11
|
+
global-exclude *.py[co]
|
|
12
|
+
global-exclude .git*
|
|
13
|
+
global-exclude *.so
|
|
14
|
+
global-exclude *.dylib
|
|
15
|
+
global-exclude *.dll
|
|
16
|
+
|
|
17
|
+
# Exclude existing bindings directory to force rebuild
|
|
18
|
+
prune masktunnellib
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: masktunnel
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python bindings for MaskTunnel (Go)
|
|
5
|
+
Home-page: https://github.com/cloudflyer-project/masktunnel
|
|
6
|
+
Author: cloudflyer-project
|
|
7
|
+
License: GPL-3.0
|
|
8
|
+
Platform: any
|
|
9
|
+
Requires-Python: >=3.9
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: setuptools>=40.0
|
|
12
|
+
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
14
|
+
Requires-Dist: pytest-xdist; extra == "dev"
|
|
15
|
+
Requires-Dist: build; extra == "dev"
|
|
16
|
+
Requires-Dist: wheel; extra == "dev"
|
|
17
|
+
Dynamic: author
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: home-page
|
|
21
|
+
Dynamic: license
|
|
22
|
+
Dynamic: platform
|
|
23
|
+
Dynamic: provides-extra
|
|
24
|
+
Dynamic: requires-dist
|
|
25
|
+
Dynamic: requires-python
|
|
26
|
+
Dynamic: summary
|
|
27
|
+
|
|
28
|
+
# masktunnel (Python bindings)
|
|
29
|
+
|
|
30
|
+
This directory contains the Python package that wraps MaskTunnel's Go implementation via gopy.
|
|
31
|
+
|
|
32
|
+
- Package name: `masktunnel`
|
|
33
|
+
- Native module directory (generated at build time): `masktunnellib/`
|
|
34
|
+
|
|
35
|
+
Build notes:
|
|
36
|
+
|
|
37
|
+
- Building from source requires Go and a C toolchain.
|
|
38
|
+
- Wheels are produced by CI for common platforms.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# masktunnel (Python bindings)
|
|
2
|
+
|
|
3
|
+
This directory contains the Python package that wraps MaskTunnel's Go implementation via gopy.
|
|
4
|
+
|
|
5
|
+
- Package name: `masktunnel`
|
|
6
|
+
- Native module directory (generated at build time): `masktunnellib/`
|
|
7
|
+
|
|
8
|
+
Build notes:
|
|
9
|
+
|
|
10
|
+
- Building from source requires Go and a C toolchain.
|
|
11
|
+
- Wheels are produced by CI for common platforms.
|
masktunnel-0.1.0/go.mod
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module github.com/cloudflyer-project/masktunnel
|
|
2
|
+
|
|
3
|
+
go 1.24.0
|
|
4
|
+
|
|
5
|
+
toolchain go1.24.4
|
|
6
|
+
|
|
7
|
+
require (
|
|
8
|
+
github.com/Noooste/azuretls-client v1.12.3
|
|
9
|
+
github.com/Noooste/fhttp v1.0.15
|
|
10
|
+
github.com/Noooste/utls v1.3.19
|
|
11
|
+
github.com/Noooste/websocket v1.0.3
|
|
12
|
+
github.com/andybalholm/brotli v1.2.0
|
|
13
|
+
github.com/cristalhq/base64 v0.1.2
|
|
14
|
+
github.com/gorilla/websocket v1.5.3
|
|
15
|
+
github.com/mileusna/useragent v1.3.4
|
|
16
|
+
github.com/rs/zerolog v1.34.0
|
|
17
|
+
github.com/spf13/pflag v1.0.10
|
|
18
|
+
github.com/valyala/fasthttp v1.65.0
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
require (
|
|
22
|
+
github.com/Noooste/go-socks4 v0.0.2 // indirect
|
|
23
|
+
github.com/Noooste/uquic-go v0.0.31 // indirect
|
|
24
|
+
github.com/bdandy/go-errors v1.2.2 // indirect
|
|
25
|
+
github.com/cloudflare/circl v1.6.1 // indirect
|
|
26
|
+
github.com/fatih/color v1.18.0 // indirect
|
|
27
|
+
github.com/gaukas/clienthellod v0.4.2 // indirect
|
|
28
|
+
github.com/gaukas/godicttls v0.0.4 // indirect
|
|
29
|
+
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
|
30
|
+
github.com/google/gopacket v1.1.19 // indirect
|
|
31
|
+
github.com/klauspost/compress v1.18.0 // indirect
|
|
32
|
+
github.com/mattn/go-colorable v0.1.14 // indirect
|
|
33
|
+
github.com/mattn/go-isatty v0.0.20 // indirect
|
|
34
|
+
github.com/quic-go/qpack v0.5.1 // indirect
|
|
35
|
+
github.com/refraction-networking/utls v1.7.3 // indirect
|
|
36
|
+
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
|
37
|
+
go.uber.org/automaxprocs v1.6.0 // indirect
|
|
38
|
+
go.uber.org/mock v0.5.2 // indirect
|
|
39
|
+
golang.org/x/crypto v0.41.0 // indirect
|
|
40
|
+
golang.org/x/mod v0.26.0 // indirect
|
|
41
|
+
golang.org/x/net v0.43.0 // indirect
|
|
42
|
+
golang.org/x/sync v0.16.0 // indirect
|
|
43
|
+
golang.org/x/sys v0.35.0 // indirect
|
|
44
|
+
golang.org/x/text v0.28.0 // indirect
|
|
45
|
+
golang.org/x/tools v0.35.0 // indirect
|
|
46
|
+
)
|
masktunnel-0.1.0/go.sum
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
github.com/Noooste/azuretls-client v1.12.3 h1:4GYXdN7J+WbGkj4oseeBUS+Eng/wm7QnAwz6gpqMjio=
|
|
2
|
+
github.com/Noooste/azuretls-client v1.12.3/go.mod h1:9PYT3hB8DWHyuL5z/iXCEYhy6v3oKazjBO1x4lqvghA=
|
|
3
|
+
github.com/Noooste/fhttp v1.0.15 h1:sYRWOKgr1x4L+wA6REMJCs4Z/lFOSJmuQHSIXMXCcPs=
|
|
4
|
+
github.com/Noooste/fhttp v1.0.15/go.mod h1:YZtq+i2M11Y22UiOR6gjNSLMNLiPhURh6M44oFVQ1TE=
|
|
5
|
+
github.com/Noooste/go-socks4 v0.0.2 h1:DwHCYiCEAdjfNrQOFIid7qgKCll7ubhGS1ji5O8FYng=
|
|
6
|
+
github.com/Noooste/go-socks4 v0.0.2/go.mod h1:+oOgtOFRsU8FoK7NBOhHSjiH5pveY8LgYNF5XcqVgjE=
|
|
7
|
+
github.com/Noooste/uquic-go v0.0.31 h1:gYIyrpcH2Znykw1dj9vsOEu0ArT8RlN46rIAehnaqMU=
|
|
8
|
+
github.com/Noooste/uquic-go v0.0.31/go.mod h1:8UUkSe8ILdcVl0/vutpZDjySNlgajKod+xlS3T3GBnE=
|
|
9
|
+
github.com/Noooste/utls v1.3.19 h1:B4HjzRTXj6T/tMBgp/u8jsbgnlitaRHEz8+0FKgZYH0=
|
|
10
|
+
github.com/Noooste/utls v1.3.19/go.mod h1:XEy+VEbTxmH6krfSG5YT7wDbjHTEi2zUXTG33R0PAAg=
|
|
11
|
+
github.com/Noooste/websocket v1.0.3 h1:drW7tvZ3YqzqI9wApnaH1Q0syFMXO7gbLlsBWjZvMNA=
|
|
12
|
+
github.com/Noooste/websocket v1.0.3/go.mod h1:Qhw0Rtuju/fPPbcb3R5XGq7poa51qPDL462jTltl9nQ=
|
|
13
|
+
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
|
|
14
|
+
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
|
|
15
|
+
github.com/bdandy/go-errors v1.2.2 h1:WdFv/oukjTJCLa79UfkGmwX7ZxONAihKu4V0mLIs11Q=
|
|
16
|
+
github.com/bdandy/go-errors v1.2.2/go.mod h1:NkYHl4Fey9oRRdbB1CoC6e84tuqQHiqrOcZpqFEkBxM=
|
|
17
|
+
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
|
|
18
|
+
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
|
19
|
+
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
|
20
|
+
github.com/cristalhq/base64 v0.1.2 h1:edsefYyYDiac7Ytdh2xdaiiSSJzcI2f0yIkdGEf1qY0=
|
|
21
|
+
github.com/cristalhq/base64 v0.1.2/go.mod h1:sy4+2Hale2KbtSqkzpdMeYTP/IrB+HCvxVHWsh2VSYk=
|
|
22
|
+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
23
|
+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
24
|
+
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
|
25
|
+
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
|
26
|
+
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
|
|
27
|
+
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
|
28
|
+
github.com/gaukas/clienthellod v0.4.2 h1:LPJ+LSeqt99pqeCV4C0cllk+pyWmERisP7w6qWr7eqE=
|
|
29
|
+
github.com/gaukas/clienthellod v0.4.2/go.mod h1:M57+dsu0ZScvmdnNxaxsDPM46WhSEdPYAOdNgfL7IKA=
|
|
30
|
+
github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
|
|
31
|
+
github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
|
|
32
|
+
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
|
33
|
+
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
|
34
|
+
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
|
35
|
+
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
|
36
|
+
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
|
37
|
+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|
38
|
+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
|
39
|
+
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
|
40
|
+
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
|
41
|
+
github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a h1://KbezygeMJZCSHH+HgUZiTeSoiuFspbMg1ge+eFj18=
|
|
42
|
+
github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
|
|
43
|
+
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
|
44
|
+
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
|
45
|
+
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
|
46
|
+
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
|
47
|
+
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
|
48
|
+
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
|
49
|
+
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
|
50
|
+
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
|
51
|
+
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
|
52
|
+
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
|
53
|
+
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
|
54
|
+
github.com/mileusna/useragent v1.3.4 h1:MiuRRuvGjEie1+yZHO88UBYg8YBC/ddF6T7F56i3PCk=
|
|
55
|
+
github.com/mileusna/useragent v1.3.4/go.mod h1:3d8TOmwL/5I8pJjyVDteHtgDGcefrFUX4ccGOMKNYYc=
|
|
56
|
+
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
|
|
57
|
+
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
|
|
58
|
+
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
|
|
59
|
+
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
|
|
60
|
+
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
61
|
+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
62
|
+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
63
|
+
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
|
64
|
+
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
|
65
|
+
github.com/refraction-networking/utls v1.7.3 h1:L0WRhHY7Oq1T0zkdzVZMR6zWZv+sXbHB9zcuvsAEqCo=
|
|
66
|
+
github.com/refraction-networking/utls v1.7.3/go.mod h1:TUhh27RHMGtQvjQq+RyO11P6ZNQNBb3N0v7wsEjKAIQ=
|
|
67
|
+
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
|
68
|
+
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
|
69
|
+
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
|
70
|
+
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
|
71
|
+
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
|
72
|
+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
|
73
|
+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
|
74
|
+
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
|
75
|
+
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
|
76
|
+
github.com/valyala/fasthttp v1.65.0 h1:j/u3uzFEGFfRxw79iYzJN+TteTJwbYkru9uDp3d0Yf8=
|
|
77
|
+
github.com/valyala/fasthttp v1.65.0/go.mod h1:P/93/YkKPMsKSnATEeELUCkG8a7Y+k99uxNHVbKINr4=
|
|
78
|
+
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
|
79
|
+
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
|
80
|
+
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
|
81
|
+
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
|
82
|
+
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
|
|
83
|
+
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
|
|
84
|
+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
85
|
+
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
86
|
+
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
|
87
|
+
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
|
88
|
+
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
|
|
89
|
+
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
|
|
90
|
+
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
|
91
|
+
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
|
92
|
+
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
|
|
93
|
+
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
|
|
94
|
+
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
95
|
+
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
96
|
+
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
|
97
|
+
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
|
98
|
+
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
99
|
+
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
|
100
|
+
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
|
101
|
+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
102
|
+
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
103
|
+
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
104
|
+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
105
|
+
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
106
|
+
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
|
107
|
+
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
|
108
|
+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
109
|
+
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
|
110
|
+
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
|
111
|
+
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
|
112
|
+
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
|
113
|
+
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
|
114
|
+
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
115
|
+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
116
|
+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""masktunnel: Python bindings for MaskTunnel (Go).
|
|
2
|
+
|
|
3
|
+
This package provides a Python-friendly API on top of the generated native bindings.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
__version__ = "0.1.0"
|
|
7
|
+
|
|
8
|
+
from ._server import Server
|
|
9
|
+
from ._utils import set_log_level
|
|
10
|
+
|
|
11
|
+
__all__ = ["Server", "set_log_level"]
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import logging
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
# Underlying Go bindings module (generated by gopy)
|
|
9
|
+
from masktunnellib import masktunnel as gomasktunnel # type: ignore
|
|
10
|
+
|
|
11
|
+
from ._utils import _logger
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class ServerOptions:
|
|
16
|
+
addr: str = ""
|
|
17
|
+
port: str = "8080"
|
|
18
|
+
user_agent: str = ""
|
|
19
|
+
payload: str = ""
|
|
20
|
+
upstream_proxy: str = ""
|
|
21
|
+
username: str = ""
|
|
22
|
+
password: str = ""
|
|
23
|
+
verbose: int = 0
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Server:
|
|
27
|
+
"""MaskTunnel proxy server.
|
|
28
|
+
|
|
29
|
+
Notes:
|
|
30
|
+
- `start()` is blocking, so typical usage is `asyncio.to_thread(server.start)`.
|
|
31
|
+
- Use `stop()` to shutdown.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, *, options: Optional[ServerOptions] = None, logger: Optional[logging.Logger] = None) -> None:
|
|
35
|
+
if logger is None:
|
|
36
|
+
logger = _logger
|
|
37
|
+
self._logger = logger
|
|
38
|
+
|
|
39
|
+
if options is None:
|
|
40
|
+
opt = gomasktunnel.DefaultServerOption()
|
|
41
|
+
else:
|
|
42
|
+
opt = gomasktunnel.DefaultServerOption()
|
|
43
|
+
opt.Addr = options.addr
|
|
44
|
+
opt.Port = options.port
|
|
45
|
+
opt.UserAgent = options.user_agent
|
|
46
|
+
opt.Payload = options.payload
|
|
47
|
+
opt.UpstreamProxy = options.upstream_proxy
|
|
48
|
+
opt.Username = options.username
|
|
49
|
+
opt.Password = options.password
|
|
50
|
+
opt.Verbose = int(options.verbose)
|
|
51
|
+
|
|
52
|
+
self._raw = gomasktunnel.NewServerHandle(opt)
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def addr(self) -> str:
|
|
56
|
+
return self._raw.Addr()
|
|
57
|
+
|
|
58
|
+
def start(self) -> None:
|
|
59
|
+
self._raw.Start()
|
|
60
|
+
|
|
61
|
+
async def async_start(self) -> None:
|
|
62
|
+
await asyncio.to_thread(self._raw.Start)
|
|
63
|
+
|
|
64
|
+
def stop(self) -> None:
|
|
65
|
+
self._raw.Stop()
|
|
66
|
+
|
|
67
|
+
async def async_stop(self) -> None:
|
|
68
|
+
await asyncio.to_thread(self._raw.Stop)
|
|
69
|
+
|
|
70
|
+
def reset_sessions(self) -> int:
|
|
71
|
+
return int(self._raw.ResetSessions())
|
|
72
|
+
|
|
73
|
+
def set_upstream_proxy(self, proxy_url: str) -> None:
|
|
74
|
+
self._raw.SetUpstreamProxy(proxy_url)
|
|
75
|
+
|
|
76
|
+
def get_ca_pem(self) -> bytes:
|
|
77
|
+
return bytes(self._raw.GetCAPEM() or b"")
|
|
78
|
+
|
|
79
|
+
def close(self) -> None:
|
|
80
|
+
try:
|
|
81
|
+
self._raw.Close()
|
|
82
|
+
except Exception:
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
async def async_close(self) -> None:
|
|
86
|
+
await asyncio.to_thread(self.close)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
_logger = logging.getLogger("masktunnel")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def set_log_level(level: int) -> None:
|
|
10
|
+
"""Set python-side log level.
|
|
11
|
+
|
|
12
|
+
Go-side logging is currently controlled by the Go application.
|
|
13
|
+
This helper only adjusts the default Python logger used by the wrappers.
|
|
14
|
+
"""
|
|
15
|
+
_logger.setLevel(level)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: masktunnel
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python bindings for MaskTunnel (Go)
|
|
5
|
+
Home-page: https://github.com/cloudflyer-project/masktunnel
|
|
6
|
+
Author: cloudflyer-project
|
|
7
|
+
License: GPL-3.0
|
|
8
|
+
Platform: any
|
|
9
|
+
Requires-Python: >=3.9
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: setuptools>=40.0
|
|
12
|
+
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
14
|
+
Requires-Dist: pytest-xdist; extra == "dev"
|
|
15
|
+
Requires-Dist: build; extra == "dev"
|
|
16
|
+
Requires-Dist: wheel; extra == "dev"
|
|
17
|
+
Dynamic: author
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: home-page
|
|
21
|
+
Dynamic: license
|
|
22
|
+
Dynamic: platform
|
|
23
|
+
Dynamic: provides-extra
|
|
24
|
+
Dynamic: requires-dist
|
|
25
|
+
Dynamic: requires-python
|
|
26
|
+
Dynamic: summary
|
|
27
|
+
|
|
28
|
+
# masktunnel (Python bindings)
|
|
29
|
+
|
|
30
|
+
This directory contains the Python package that wraps MaskTunnel's Go implementation via gopy.
|
|
31
|
+
|
|
32
|
+
- Package name: `masktunnel`
|
|
33
|
+
- Native module directory (generated at build time): `masktunnellib/`
|
|
34
|
+
|
|
35
|
+
Build notes:
|
|
36
|
+
|
|
37
|
+
- Building from source requires Go and a C toolchain.
|
|
38
|
+
- Wheels are produced by CI for common platforms.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
MANIFEST.in
|
|
2
|
+
README.md
|
|
3
|
+
go.mod
|
|
4
|
+
go.sum
|
|
5
|
+
setup.py
|
|
6
|
+
masktunnel/__init__.py
|
|
7
|
+
masktunnel/_server.py
|
|
8
|
+
masktunnel/_utils.py
|
|
9
|
+
masktunnel.egg-info/PKG-INFO
|
|
10
|
+
masktunnel.egg-info/SOURCES.txt
|
|
11
|
+
masktunnel.egg-info/dependency_links.txt
|
|
12
|
+
masktunnel.egg-info/not-zip-safe
|
|
13
|
+
masktunnel.egg-info/requires.txt
|
|
14
|
+
masktunnel.egg-info/top_level.txt
|
|
15
|
+
masktunnel_go/_python.go
|
|
16
|
+
masktunnel_go/basic.go
|
|
17
|
+
masktunnel_go/bindings.go
|
|
18
|
+
masktunnel_go/config.go
|
|
19
|
+
masktunnel_go/encoding.go
|
|
20
|
+
masktunnel_go/generator.go
|
|
21
|
+
masktunnel_go/manager.go
|
|
22
|
+
masktunnel_go/mitm.go
|
|
23
|
+
masktunnel_go/payload.go
|
|
24
|
+
masktunnel_go/python.go
|
|
25
|
+
masktunnel_go/server.go
|
|
26
|
+
masktunnel_go/ua_parser.go
|
|
27
|
+
tests/test_server.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
package masktunnel
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"sync"
|
|
6
|
+
"time"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
// This file provides small, gopy-friendly helpers for Python bindings.
|
|
10
|
+
|
|
11
|
+
// ========== Context helpers ==========
|
|
12
|
+
|
|
13
|
+
var (
|
|
14
|
+
globalCtx context.Context
|
|
15
|
+
globalCancel context.CancelFunc
|
|
16
|
+
globalOnce sync.Once
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
// Background returns a process-wide background context.
|
|
20
|
+
func Background() context.Context {
|
|
21
|
+
globalOnce.Do(func() {
|
|
22
|
+
globalCtx, globalCancel = context.WithCancel(context.Background())
|
|
23
|
+
})
|
|
24
|
+
return globalCtx
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// ContextWithCancel wraps a context and its cancel function.
|
|
28
|
+
type ContextWithCancel struct {
|
|
29
|
+
ctx context.Context
|
|
30
|
+
cancel context.CancelFunc
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// NewContextWithCancel creates a new cancellable context.
|
|
34
|
+
func NewContextWithCancel() *ContextWithCancel {
|
|
35
|
+
ctx, cancel := context.WithCancel(context.Background())
|
|
36
|
+
return &ContextWithCancel{ctx: ctx, cancel: cancel}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Cancel cancels the underlying context.
|
|
40
|
+
func (c *ContextWithCancel) Cancel() {
|
|
41
|
+
if c != nil && c.cancel != nil {
|
|
42
|
+
c.cancel()
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Context returns the underlying context.
|
|
47
|
+
func (c *ContextWithCancel) Context() context.Context {
|
|
48
|
+
if c == nil {
|
|
49
|
+
return context.Background()
|
|
50
|
+
}
|
|
51
|
+
return c.ctx
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// CancelGlobalContext cancels the global background context.
|
|
55
|
+
func CancelGlobalContext() {
|
|
56
|
+
if globalCancel != nil {
|
|
57
|
+
globalCancel()
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// NewContext returns a new background-derived context.
|
|
62
|
+
func NewContext() context.Context {
|
|
63
|
+
ctx, _ := context.WithCancel(context.Background())
|
|
64
|
+
return ctx
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ========== Time constants ==========
|
|
68
|
+
|
|
69
|
+
var (
|
|
70
|
+
Nanosecond = time.Nanosecond
|
|
71
|
+
Microsecond = time.Microsecond
|
|
72
|
+
Millisecond = time.Millisecond
|
|
73
|
+
Second = time.Second
|
|
74
|
+
Minute = time.Minute
|
|
75
|
+
Hour = time.Hour
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
// ParseDuration parses a duration string (e.g. "300ms", "2h45m").
|
|
79
|
+
func ParseDuration(s string) (time.Duration, error) {
|
|
80
|
+
return time.ParseDuration(s)
|
|
81
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
package masktunnel
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/base64"
|
|
5
|
+
"net/http"
|
|
6
|
+
"strings"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
// BasicAuth handles HTTP Basic Authentication for proxy
|
|
10
|
+
type BasicAuth struct {
|
|
11
|
+
username string
|
|
12
|
+
password string
|
|
13
|
+
enabled bool
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// NewBasicAuth creates a new basic auth handler
|
|
17
|
+
func NewBasicAuth(username, password string) *BasicAuth {
|
|
18
|
+
return &BasicAuth{
|
|
19
|
+
username: username,
|
|
20
|
+
password: password,
|
|
21
|
+
enabled: username != "" || password != "",
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// IsEnabled returns true if authentication is enabled
|
|
26
|
+
func (ba *BasicAuth) IsEnabled() bool {
|
|
27
|
+
return ba.enabled
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Validate validates the proxy authentication from request
|
|
31
|
+
func (ba *BasicAuth) Validate(req *http.Request) bool {
|
|
32
|
+
if !ba.enabled {
|
|
33
|
+
return true
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
authHeader := req.Header.Get("Proxy-Authorization")
|
|
37
|
+
if authHeader == "" {
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if !strings.HasPrefix(authHeader, "Basic ") {
|
|
42
|
+
return false
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
encoded := authHeader[6:] // Remove "Basic " prefix
|
|
46
|
+
decoded, err := base64.StdEncoding.DecodeString(encoded)
|
|
47
|
+
if err != nil {
|
|
48
|
+
return false
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
credentials := string(decoded)
|
|
52
|
+
parts := strings.SplitN(credentials, ":", 2)
|
|
53
|
+
if len(parts) != 2 {
|
|
54
|
+
return false
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return parts[0] == ba.username && parts[1] == ba.password
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// GetAuthRequiredResponse returns HTTP 407 response for auth required
|
|
61
|
+
func (ba *BasicAuth) GetAuthRequiredResponse() *http.Response {
|
|
62
|
+
resp := &http.Response{
|
|
63
|
+
StatusCode: http.StatusProxyAuthRequired,
|
|
64
|
+
Status: "407 Proxy Authentication Required",
|
|
65
|
+
Proto: "HTTP/1.1",
|
|
66
|
+
ProtoMajor: 1,
|
|
67
|
+
ProtoMinor: 1,
|
|
68
|
+
Header: make(http.Header),
|
|
69
|
+
Body: http.NoBody,
|
|
70
|
+
ContentLength: 0,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
resp.Header.Set("Proxy-Authenticate", "Basic realm=\"MaskTunnel Proxy\"")
|
|
74
|
+
resp.Header.Set("Content-Type", "text/plain")
|
|
75
|
+
|
|
76
|
+
return resp
|
|
77
|
+
}
|