diff options
Diffstat (limited to 'tunnel/tools')
-rw-r--r-- | tunnel/tools/libwg-go/Makefile | 2 | ||||
-rw-r--r-- | tunnel/tools/libwg-go/api-android.go | 3 | ||||
-rw-r--r-- | tunnel/tools/libwg-go/go.mod | 3 | ||||
-rw-r--r-- | tunnel/tools/libwg-go/go.sum | 5 | ||||
-rw-r--r-- | tunnel/tools/libwg-go/http-proxy.go | 165 | ||||
-rw-r--r-- | tunnel/tools/libwg-go/service.go | 123 |
6 files changed, 297 insertions, 4 deletions
diff --git a/tunnel/tools/libwg-go/Makefile b/tunnel/tools/libwg-go/Makefile index 2dc76955..189807d2 100644 --- a/tunnel/tools/libwg-go/Makefile +++ b/tunnel/tools/libwg-go/Makefile @@ -71,7 +71,7 @@ gen/%_grpc.pb.go: $(PROTODIR)/%.proto $(BUILDDIR)/go-$(GO_VERSION)/.prepared $(P $(PROTOC) -I $(PROTODIR) -I $(PROTO_INCLUDEDIR) --go-grpc_out=./gen --go-grpc_opt=paths=source_relative $< $(DESTDIR)/libwg-go.so: export PATH := $(BUILDDIR)/go-$(GO_VERSION)/bin/:$(PATH) -$(DESTDIR)/libwg-go.so: $(BUILDDIR)/go-$(GO_VERSION)/.prepared go.mod api-android.go service.go gen/libwg.pb.go gen/libwg_grpc.pb.go jni.c +$(DESTDIR)/libwg-go.so: $(BUILDDIR)/go-$(GO_VERSION)/.prepared go.mod api-android.go http-proxy.go service.go gen/libwg.pb.go gen/libwg_grpc.pb.go jni.c go build -tags linux -ldflags="-X golang.zx2c4.com/wireguard/ipc.socketDirectory=/data/data/$(ANDROID_PACKAGE_NAME)/cache/wireguard" -v -trimpath -o "$@" -buildmode c-shared .DELETE_ON_ERROR: diff --git a/tunnel/tools/libwg-go/api-android.go b/tunnel/tools/libwg-go/api-android.go index d0086a75..01608923 100644 --- a/tunnel/tools/libwg-go/api-android.go +++ b/tunnel/tools/libwg-go/api-android.go @@ -231,7 +231,7 @@ func Version() string { //export wgStartGrpc func wgStartGrpc(sock_path string) C.int{ - tag := cstring("helloworld") + tag := cstring("WireGuard/GoBackend/gRPC") logger := &device.Logger{ Verbosef: AndroidLogger{level: C.ANDROID_LOG_DEBUG, tag: tag}.Printf, Errorf: AndroidLogger{level: C.ANDROID_LOG_ERROR, tag: tag}.Printf, @@ -240,6 +240,7 @@ func wgStartGrpc(sock_path string) C.int{ res, errmsg := StartGrpc(sock_path, logger) logger.Verbosef("wgStartGrpc: %v %v", res, errmsg) + return C.int(res) } diff --git a/tunnel/tools/libwg-go/go.mod b/tunnel/tools/libwg-go/go.mod index 33aa796d..3d24d309 100644 --- a/tunnel/tools/libwg-go/go.mod +++ b/tunnel/tools/libwg-go/go.mod @@ -3,7 +3,9 @@ module golang.zx2c4.com/wireguard/android go 1.17 require ( + github.com/elazarl/goproxy v0.0.0-20211114080932-d06c3be7c11b golang.org/x/sys v0.0.0-20211110154304-99a53858aa08 + golang.zx2c4.com/go118/netip v0.0.0-20211111135330-a4a02eeacf9d golang.zx2c4.com/wireguard v0.0.0-20211111141719-cad0ff2cfbd9 google.golang.org/grpc v1.42.0-dev.0.20211020220737-f00baa6c3c84 google.golang.org/protobuf v1.27.1 @@ -14,7 +16,6 @@ require ( golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa // indirect golang.org/x/net v0.0.0-20211111083644-e5c967477495 // indirect golang.org/x/text v0.3.6 // indirect - golang.zx2c4.com/go118/netip v0.0.0-20211111135330-a4a02eeacf9d // indirect golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f // indirect ) diff --git a/tunnel/tools/libwg-go/go.sum b/tunnel/tools/libwg-go/go.sum index f5bc4340..c68fb496 100644 --- a/tunnel/tools/libwg-go/go.sum +++ b/tunnel/tools/libwg-go/go.sum @@ -13,6 +13,10 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/elazarl/goproxy v0.0.0-20211114080932-d06c3be7c11b h1:1XqENn2YoYZd6w3Awx+7oa+aR87DFIZJFLF2n1IojA0= +github.com/elazarl/goproxy v0.0.0-20211114080932-d06c3be7c11b/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM= +github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -49,6 +53,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/tunnel/tools/libwg-go/http-proxy.go b/tunnel/tools/libwg-go/http-proxy.go new file mode 100644 index 00000000..4af97314 --- /dev/null +++ b/tunnel/tools/libwg-go/http-proxy.go @@ -0,0 +1,165 @@ +package main + +import ( + "net" + "net/http" + "net/url" + + "github.com/elazarl/goproxy" + + "golang.zx2c4.com/go118/netip" + "golang.zx2c4.com/wireguard/device" +) + +type HttpProxy struct { + listener net.Listener + logger *device.Logger + addrPort netip.AddrPort + uidRequest chan netip.AddrPort + uidResponse chan string +} + +func NewHttpProxy(uidRequest chan netip.AddrPort, uidResponse chan string, logger *device.Logger) *HttpProxy { + logger.Verbosef("NewHttpProxy") + return &HttpProxy{ + listener: nil, + logger: logger, + uidRequest: uidRequest, + uidResponse: uidResponse, + } +} + +func (p *HttpProxy) GetAddrPort() netip.AddrPort { + return p.addrPort +} + +func newGoProxy(proxyUrl string) *goproxy.ProxyHttpServer { + proxy := goproxy.NewProxyHttpServer() + proxy.Verbose = true + proxy.Tr.Proxy = func(req *http.Request) (*url.URL, error) { + return url.Parse(proxyUrl) + } + proxy.ConnectDial = proxy.NewConnectDialToProxy(proxyUrl) + + return proxy +} + +func (p *HttpProxy) Start() (listen_port uint16, err error) { + p.logger.Verbosef("HttpProxy.Start()") + listen_port = 0 + + proxyMap := make(map[string]*goproxy.ProxyHttpServer) + proxyMap["bbc.iplayer.android"] = newGoProxy("http://10.49.124.111:8888") + proxyMap["no.nrk.tv"] = newGoProxy("http://10.49.124.115:8888") + + defaultProxy := goproxy.NewProxyHttpServer() + defaultProxy.Verbose = true + + listener, err := net.Listen("tcp", "localhost:") + if err != nil { + return + } + + p.addrPort, err = netip.ParseAddrPort(listener.Addr().String()) + if err != nil { + return + } + + listen_port = p.addrPort.Port() + + handler := NewHttpHandler(proxyMap, defaultProxy, p.logger) + + go http.Serve(NewUidListener(listener, handler, p.uidRequest, p.uidResponse, p.logger), handler) + + return +} + +func (p *HttpProxy) Stop() { + if p.listener != nil { + p.logger.Verbosef("Close: %v", p.listener) + p.listener.Close() + p.listener = nil + } +} + +type HttpHandler struct { + proxyMap map[string]*goproxy.ProxyHttpServer + defaultProxy *goproxy.ProxyHttpServer + logger *device.Logger + remoteAddrPkgMap map[string]string +} + +func NewHttpHandler(proxyMap map[string]*goproxy.ProxyHttpServer, defaultProxy *goproxy.ProxyHttpServer, logger *device.Logger) *HttpHandler{ + return &HttpHandler{ + proxyMap: proxyMap, + defaultProxy: defaultProxy, + logger: logger, + remoteAddrPkgMap: make(map[string]string), + } +} + +func (h *HttpHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + pkg, ok := h.remoteAddrPkgMap[req.RemoteAddr] + if ok { + h.logger.Verbosef("ServeHTTP remote:%s package:%s", req.RemoteAddr, pkg) + delete(h.remoteAddrPkgMap, req.RemoteAddr) + + proxy, ok := h.proxyMap[pkg] + if ok { + proxy.ServeHTTP(rw, req) + } else { + h.defaultProxy.ServeHTTP(rw, req) + } + } else { + h.defaultProxy.ServeHTTP(rw, req) + } +} + +// UidListener +type UidListener struct { + l net.Listener + handler *HttpHandler + logger *device.Logger + uidRequest chan netip.AddrPort + uidResponse chan string +} + +func NewUidListener(listener net.Listener, handler *HttpHandler, uidRequest chan netip.AddrPort, uidResponse chan string, logger *device.Logger) *UidListener{ + return &UidListener{ + l: listener, + handler: handler, + logger: logger, + uidRequest: uidRequest, + uidResponse: uidResponse, + } +} + +func (l *UidListener) Accept() (net.Conn, error) { + c, err := l.l.Accept() + if err != nil { + return c, err + } + + l.logger.Verbosef("Accept: %v", c.RemoteAddr().String()) + addr_port, err := netip.ParseAddrPort(c.RemoteAddr().String()) + if err == nil { + l.logger.Verbosef("uidRequest") + l.uidRequest <- addr_port + + // TODO add timeout? + select { + case pkg := <-l.uidResponse: + l.logger.Verbosef("uidResponse: %v", pkg) + l.handler.remoteAddrPkgMap[c.RemoteAddr().String()] = pkg + } + } + return c, nil +} + +func (l *UidListener) Close() error { + return l.l.Close() +} + +func (l *UidListener) Addr() net.Addr { + return l.l.Addr() +} diff --git a/tunnel/tools/libwg-go/service.go b/tunnel/tools/libwg-go/service.go index 780ab8c8..c201e45d 100644 --- a/tunnel/tools/libwg-go/service.go +++ b/tunnel/tools/libwg-go/service.go @@ -3,26 +3,41 @@ package main import ( "context" "fmt" + "io" "net" "os" "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/emptypb" + "golang.zx2c4.com/go118/netip" gen "golang.zx2c4.com/wireguard/android/gen" "golang.zx2c4.com/wireguard/device" ) +const ( + IPPROTO_TCP = 6 +) + type LibwgServiceImpl struct { gen.UnimplementedLibwgServer logger *device.Logger + http_proxy *HttpProxy + uidRequest chan netip.AddrPort + uidResponse chan string } var _ gen.LibwgServer = (*LibwgServiceImpl)(nil) var server *grpc.Server func NewLibwgService(logger *device.Logger) gen.LibwgServer { - return &LibwgServiceImpl{logger: logger} + return &LibwgServiceImpl{ + logger: logger, + uidRequest: make(chan netip.AddrPort), + uidResponse: make(chan string), + } } func StartGrpc(sock_path string, logger *device.Logger) (int, string) { @@ -77,3 +92,109 @@ func (e *LibwgServiceImpl) StopGrpc(ctx context.Context, req *emptypb.Empty) (*e return r, nil } + +func (e *LibwgServiceImpl) StartHttpProxy(ctx context.Context, req *gen.StartHttpProxyRequest) (*gen.StartHttpProxyResponse, error) { + if e.http_proxy != nil { + listen_port := e.http_proxy.GetAddrPort().Port() + r := &gen.StartHttpProxyResponse{ + ListenPort: uint32(listen_port), + Error: &gen.Error{ + Message: fmt.Sprintf("Http proxy already running"), + }, + } + return r, nil + } + + e.http_proxy = NewHttpProxy(e.uidRequest, e.uidResponse, e.logger) + listen_port, err := e.http_proxy.Start() + + if err != nil { + r := &gen.StartHttpProxyResponse{ + Error: &gen.Error{ + Message: fmt.Sprintf("Http proxy start: %v", err), + }, + } + return r, nil + } + + r := &gen.StartHttpProxyResponse{ + ListenPort: uint32(listen_port), + } + + e.logger.Verbosef("Started http proxy") + return r, nil +} + +func (e *LibwgServiceImpl) StopHttpProxy(ctx context.Context, req *gen.StopHttpProxyRequest) (*gen.StopHttpProxyResponse, error) { + if e.http_proxy == nil { + r := &gen.StopHttpProxyResponse{ + Error: &gen.Error{ + Message: fmt.Sprintf("Http proxy not running"), + }, + } + return r, nil + } + + e.http_proxy.Stop() + e.http_proxy = nil + r := &gen.StopHttpProxyResponse{} + e.logger.Verbosef("Stopped http proxy") + return r, nil +} + +func (e *LibwgServiceImpl) Reverse(stream gen.Libwg_ReverseServer) error { + e.logger.Verbosef("Reverse enter loop") + for { + var err error + + // err := contextError(stream.Context()) + err = stream.Context().Err() + if err != nil { + e.logger.Verbosef("Reverse: context: %v", err) + return err + } + + select { + case addr_port := <-e.uidRequest: + r := &gen.ReverseResponse{ + Request: &gen.ReverseResponse_Uid{ + Uid: &gen.GetConnectionOwnerUidRequest{ + Protocol: IPPROTO_TCP, + Local: &gen.InetSocketAddress{ + Address: &gen.InetAddress{ + Address: addr_port.Addr().AsSlice(), + }, + Port: uint32(addr_port.Port()), + }, + Remote: &gen.InetSocketAddress{ + Address: &gen.InetAddress{ + Address: e.http_proxy.GetAddrPort().Addr().AsSlice(), + }, + Port: uint32(e.http_proxy.GetAddrPort().Port()), + }, + }, + }, + } + + stream.Send(r) + } + + req, err := stream.Recv() + if err == io.EOF { + e.logger.Verbosef("no more data") + break + } + if err != nil { + err = status.Errorf(codes.Unknown, "cannot receive stream request: %v", err) + e.logger.Verbosef("Reverse: %v", err) + return err + } + + e.logger.Verbosef("Reverse: received, wait: %v", req) + e.uidResponse <- req.GetUid().GetPackage() + } + + + e.logger.Verbosef("Reverse returns") + return nil +} |