diff options
author | Mikael Magnusson <mikma@users.sourceforge.net> | 2022-03-29 23:51:21 +0200 |
---|---|---|
committer | Mikael Magnusson <mikma@users.sourceforge.net> | 2023-03-30 23:17:27 +0200 |
commit | cb125c60ec3e7c4298b63be3d8777d1b600d3c34 (patch) | |
tree | a45c9787c618a8ef246c481890f80f466f993882 /tunnel/tools/libwg-go/service.go | |
parent | b5f795dfbea379f026a97ef90ed3d1c27647c592 (diff) |
tunnel: implement http proxy for Android 10+
Allow getting package names of tv apps.
Diffstat (limited to 'tunnel/tools/libwg-go/service.go')
-rw-r--r-- | tunnel/tools/libwg-go/service.go | 149 |
1 files changed, 146 insertions, 3 deletions
diff --git a/tunnel/tools/libwg-go/service.go b/tunnel/tools/libwg-go/service.go index 2a0dfb2d..37fb4b40 100644 --- a/tunnel/tools/libwg-go/service.go +++ b/tunnel/tools/libwg-go/service.go @@ -3,25 +3,45 @@ package main import ( "context" "fmt" + "io" "net" + "net/url" "os" "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" gen "golang.zx2c4.com/wireguard/android/gen" "golang.zx2c4.com/wireguard/device" ) +const ( + IPPROTO_TCP = 6 +) + +type UidRequest struct { + Data AddrPortPair + RetCh chan string +} + type LibwgServiceImpl struct { gen.UnimplementedLibwgServer logger *device.Logger + httpProxy *HttpProxy + uidRequest chan UidRequest + stopReverse chan bool } -var _ gen.LibwgServer = (*LibwgServiceImpl)(nil) +var service *LibwgServiceImpl var server *grpc.Server func NewLibwgService(logger *device.Logger) gen.LibwgServer { - return &LibwgServiceImpl{logger: logger} + return &LibwgServiceImpl{ + logger: logger, + uidRequest: make(chan UidRequest), + stopReverse: make(chan bool), + } } func StartGrpc(sock_path string, logger *device.Logger) (int, string) { @@ -41,7 +61,7 @@ func StartGrpc(sock_path string, logger *device.Logger) (int, string) { } server = grpc.NewServer() - service := NewLibwgService(logger) + service = NewLibwgService(logger).(*LibwgServiceImpl) gen.RegisterLibwgServer(server, service) @@ -67,6 +87,7 @@ func (e *LibwgServiceImpl) StopGrpc(ctx context.Context, req *gen.StopGrpcReques if server != nil { server.Stop() server = nil + service = nil } r := &gen.StopGrpcResponse{ @@ -74,3 +95,125 @@ func (e *LibwgServiceImpl) StopGrpc(ctx context.Context, req *gen.StopGrpcReques return r, nil } + +func buildStartHttpProxyError(message string) (*gen.StartHttpProxyResponse, error) { + r := &gen.StartHttpProxyResponse{ + Error: &gen.Error{ + Message: message, + }, + } + return r, nil +} + +func (e *LibwgServiceImpl) StartHttpProxy(ctx context.Context, req *gen.StartHttpProxyRequest) (*gen.StartHttpProxyResponse, error) { + var listenPort uint16 + if e.httpProxy == nil { + e.httpProxy = NewHttpProxy(e.uidRequest, e.logger) + var err error + listenPort, err = e.httpProxy.Start() + + if err != nil { + e.httpProxy = nil + return buildStartHttpProxyError(fmt.Sprintf("Http proxy start failed: %v", err)) + } + } else { + listenPort = e.httpProxy.GetAddrPort().Port() + } + + pacFileUrl, err := url.Parse(req.PacFileUrl) + if err != nil { + return buildStartHttpProxyError(fmt.Sprintf("Bad pacFileUrl: %v (%s)", err, req.PacFileUrl)) + } + + err = e.httpProxy.SetPacFileUrl(pacFileUrl) + if err != nil { + return buildStartHttpProxyError(fmt.Sprintf("Bad pacFileUrl: %v (%s)", req.PacFileUrl)) + } + + r := &gen.StartHttpProxyResponse{ + ListenPort: uint32(listenPort), + } + return r, nil +} + +func (e *LibwgServiceImpl) StopHttpProxy(ctx context.Context, req *gen.StopHttpProxyRequest) (*gen.StopHttpProxyResponse, error) { + if e.httpProxy == nil { + r := &gen.StopHttpProxyResponse{ + Error: &gen.Error{ + Message: fmt.Sprintf("Http proxy not running"), + }, + } + return r, nil + } + + e.httpProxy.Stop() + e.httpProxy = nil + e.stopReverse <- true + r := &gen.StopHttpProxyResponse{} + return r, nil +} + +func (e *LibwgServiceImpl) Reverse(stream gen.Libwg_ReverseServer) error { + e.logger.Verbosef("Reverse enter loop") + for e.httpProxy != nil { + 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 <-e.stopReverse: + e.logger.Verbosef("Reverse: stop") + break + case uidReq := <-e.uidRequest: + addrPortPair := uidReq.Data + local := addrPortPair.local + remote := addrPortPair.remote + r := &gen.ReverseResponse{ + Request: &gen.ReverseResponse_Uid{ + Uid: &gen.GetConnectionOwnerUidRequest{ + Protocol: IPPROTO_TCP, + Local: &gen.InetSocketAddress{ + Address: &gen.InetAddress{ + Address: local.Addr().AsSlice(), + }, + Port: uint32(local.Port()), + }, + Remote: &gen.InetSocketAddress{ + Address: &gen.InetAddress{ + Address: remote.Addr().AsSlice(), + }, + Port: uint32(remote.Port()), + }, + }, + }, + } + + stream.Send(r) + + req, err := stream.Recv() + if err == io.EOF { + e.logger.Verbosef("no more data") + uidReq.RetCh <- "" + break + } + if err != nil { + err = status.Errorf(codes.Unknown, "cannot receive stream request: %v", err) + e.logger.Verbosef("Reverse: %v", err) + uidReq.RetCh <- "" + return err + } + + e.logger.Verbosef("Reverse: received, wait: %v", req) + uidReq.RetCh <- req.GetUid().GetPackage() + } + } + + + e.logger.Verbosef("Reverse returns") + return nil +} |