summaryrefslogtreecommitdiffhomepage
path: root/tunnel/tools/libwg-go/service.go
diff options
context:
space:
mode:
authorMikael Magnusson <mikma@users.sourceforge.net>2022-03-29 23:51:21 +0200
committerMikael Magnusson <mikma@users.sourceforge.net>2022-06-10 22:22:06 +0200
commit1c5822e2b7ec9227765a684d05d57c65eafc5e52 (patch)
tree608ccfe046226ade594ee703f06267eb353cb33e /tunnel/tools/libwg-go/service.go
parent295e5d7d682903ac440ca1e7ca1f27f017494c35 (diff)
tunnel: implement http proxy for Android 10+
Diffstat (limited to 'tunnel/tools/libwg-go/service.go')
-rw-r--r--tunnel/tools/libwg-go/service.go149
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
+}