Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
mrjosh committed Oct 28, 2022
0 parents commit 9d4b03a
Show file tree
Hide file tree
Showing 12 changed files with 955 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/sandbox
/dist
/bin
/cert
42 changes: 42 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
export ROOT=$(realpath $(dir $(firstword $(MAKEFILE_LIST))))
export BIN=$(ROOT)/bin
export GOBIN?=$(BIN)
export GO=$(shell which go)
export CGO_ENABLED=1
export PROTO_OUT=$(ROOT)
export GOX=$(BIN)/gox

proto:
@protoc \
-Iprotofiles \
--go_out=${PROTO_OUT} \
--go-grpc_out=${PROTO_OUT} \
protofiles/*.proto
.PHONY: proto

install-gox:
@$(GO) install github.com/mitchellh/[email protected]

.PHONY: build-linux
build-linux: install-gox
@$(GOX) --arch=amd64 --os=linux --output="dist/utg_{{.OS}}_{{.Arch}}"

.PHONY: build-macOS
build-macOS: install-gox
@$(GOX) --arch=amd64 --os=darwin --output="dist/utg_{{.OS}}_{{.Arch}}"

.PHONY: build-windows
build-windows: install-gox
@$(GOX) -ldflags ${GO_LDFLAGS} --arch=amd64 --os=windows --output="dist/utg_{{.OS}}_{{.Arch}}"

.PHONY: build-artifacts
build-artifacts:
@$(MAKE) build-linux && \
$(MAKE) build-macOS && \
$(MAKE) build-windows

cert:
@openssl genrsa -out cert/ca.key 2048
@openssl req -new -x509 -days 365 -key cert/ca.key -subj "/C=CN/ST=GD/L=SZ/O=Acme, Inc./CN=Acme Root CA" -out cert/ca.crt
@openssl req -newkey rsa:2048 -nodes -keyout cert/server.key -subj "/C=CN/ST=GD/L=SZ/O=Acme, Inc./CN=*.mrjosh.net" -out cert/server.csr
@openssl x509 -req -extfile <(printf "subjectAltName=DNS:mrjosh.net,DNS:u2g.mrjosh.net") -days 365 -in cert/server.csr -CA cert/ca.crt -CAkey cert/ca.key -CAcreateserial -out cert/server.crt
93 changes: 93 additions & 0 deletions cmds/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package cmds

import (
"context"
"fmt"
"log"

"github.com/mrjosh/udp2grpc/internal/client"
"github.com/mrjosh/udp2grpc/proto"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)

type NewClientFlags struct {
localaddr, remoteaddr string
localport, remoteport int
insecure bool
certFile, serverNameOverride string
}

func NewClientCommand() *cobra.Command {

log.SetFlags(log.Lshortfile)
cFlags := new(NewClientFlags)

cmd := &cobra.Command{
Use: "client",
Short: "Start a udp2grpc tcp/client",
RunE: func(cmd *cobra.Command, args []string) error {

if cFlags.remoteaddr == "" {
return errors.New("server remote address is required. try 'utg client --address domain.tld'")
}

opts := []grpc.DialOption{}
if cFlags.insecure {
opts = append(opts, grpc.WithInsecure())
}

if !cFlags.insecure {

if cFlags.certFile == "" {
return errors.New("--tls-cert-file flag is required in tls mode. turn off tls mode with --insecure flag")
}

creds, err := credentials.NewClientTLSFromFile(cFlags.certFile, cFlags.serverNameOverride)
if err != nil {
log.Fatalln(err)
}
opts = append(opts, grpc.WithTransportCredentials(creds))
}

addr := fmt.Sprintf("%s:%d", cFlags.remoteaddr, cFlags.remoteport)

conn, err := grpc.Dial(addr, opts...)
if err != nil {
return fmt.Errorf("did not connect: %v", err)
}

c := proto.NewVPNServiceClient(conn)

log.Println(fmt.Sprintf("Connecting to tcp:%s", addr))

callOpts := grpc.EmptyCallOption{}
stream, err := c.Connect(context.Background(), callOpts)
if err != nil {
return err
}

log.Println(fmt.Sprintf("Connected to tcp:%s", addr))

ic, err := client.NewClient(fmt.Sprintf("%s:%d", cFlags.localaddr, cFlags.localport), stream)
if err != nil {
return err
}
defer ic.Close()

return ic.Listen()
},
}

cmd.SuggestionsMinimumDistance = 1
cmd.Flags().StringVarP(&cFlags.remoteaddr, "remote-address", "r", "", "Server remote address")
cmd.Flags().IntVarP(&cFlags.remoteport, "port", "p", 52935, "Server tcp port")
cmd.Flags().StringVarP(&cFlags.localaddr, "local-address", "l", "", "Local server address")
cmd.Flags().IntVarP(&cFlags.localport, "local-port", "P", 52935, "Local server port")
cmd.Flags().StringVarP(&cFlags.certFile, "tls-cert-file", "c", "", "Server TLS certificate file")
cmd.Flags().StringVarP(&cFlags.serverNameOverride, "tls-server-name", "o", "", "TLS server name override")
cmd.Flags().BoolVarP(&cFlags.insecure, "insecure", "k", false, "Connect to server without tls")
return cmd
}
146 changes: 146 additions & 0 deletions cmds/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package cmds

import (
"crypto/tls"
"fmt"
"log"
"net"
"strconv"
"strings"
"time"

"github.com/mrjosh/udp2grpc/internal/service"
"github.com/mrjosh/udp2grpc/proto"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/keepalive"
"google.golang.org/grpc/reflection"
)

type NewServerFlags struct {
localaddr, remoteaddr string
port int
insecure bool
certFile, keyFile string
}

func NewServerCommand() *cobra.Command {

log.SetFlags(log.Lshortfile)
cFlags := new(NewServerFlags)

cmd := &cobra.Command{
Use: "server",
Short: "Start a udp2grpc tcp/server",
RunE: func(cmd *cobra.Command, args []string) error {

if cFlags.remoteaddr == "" {
return fmt.Errorf("Server remote address is required. try with flag 'utg server --remote-address=\"127.0.0.1\" '")
}

listener, err := net.Listen("tcp4", fmt.Sprintf("%s:%d", cFlags.localaddr, cFlags.port))
if err != nil {
return fmt.Errorf("could not create tcp listener: %v", err)
}

kaParams := keepalive.ServerParameters{
Time: 10 * time.Second,
Timeout: 5 * time.Second,
}

enforcement := keepalive.EnforcementPolicy{
MinTime: 3 * time.Second,
PermitWithoutStream: true,
}

opts := []grpc.ServerOption{
grpc.KeepaliveParams(kaParams),
grpc.KeepaliveEnforcementPolicy(enforcement),
}

if !cFlags.insecure {

if cFlags.certFile == "" {
return errors.New("--tls-cert-file flag is required in tls mode. turn off tls mode with --insecure flag")
}

if cFlags.keyFile == "" {
return errors.New("--tls-key-file flag is required in tls mode. turn off tls mode with --insecure flag")
}

tlsCredentials, err := loadTLSCredentials(cFlags.certFile, cFlags.keyFile)
if err != nil {
return err
}

opts = append(opts, grpc.Creds(credentials.NewServerTLSFromCert(tlsCredentials)))
}

server := grpc.NewServer(opts...)

remoteConn, err := createRemoteConnection(cFlags.remoteaddr)
if err != nil {
return err
}

// Register binance services
svc := service.NewVPNService(remoteConn)
defer svc.Close()

proto.RegisterVPNServiceServer(server, svc)

reflection.Register(server)

log.Println(fmt.Sprintf("Server running in tcp:%s:%d", cFlags.localaddr, cFlags.port))
if err := server.Serve(listener); err != nil {
return fmt.Errorf("could not serve grpc.tcp.listener: %v", err)
}

return nil
},
}
cmd.SuggestionsMinimumDistance = 1
cmd.Flags().StringVarP(&cFlags.localaddr, "local-address", "l", "0.0.0.0", "Local server address")
cmd.Flags().StringVarP(&cFlags.remoteaddr, "remote-address", "r", "", "Remote address")
cmd.Flags().IntVarP(&cFlags.port, "port", "p", 52935, "Local server port")
cmd.Flags().StringVarP(&cFlags.certFile, "tls-cert-file", "c", "", "Server TLS certificate file")
cmd.Flags().StringVarP(&cFlags.keyFile, "tls-key-file", "s", "", "Server TLS key file")
cmd.Flags().BoolVarP(&cFlags.insecure, "insecure", "k", false, "Start the server without tls")
return cmd
}

func createRemoteConnection(address string) (*net.UDPConn, error) {

remote := strings.Split(address, ":")
rport, err := strconv.Atoi(remote[1])
if err != nil {
log.Fatal(errors.New("listen flag should contains ip:port"))
}

remoteConn, err := net.DialUDP(
"udp",
&net.UDPAddr{},
&net.UDPAddr{
IP: net.ParseIP(remote[0]),
Port: rport,
},
)

if err != nil {
return nil, err
}

return remoteConn, nil
}

func loadTLSCredentials(certFile, keyFile string) (*tls.Certificate, error) {
// Load server's certificate and private key
serverCert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, err
}

return &serverCert, nil
}
20 changes: 20 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module github.com/mrjosh/udp2grpc

go 1.19

require (
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.6.1
google.golang.org/grpc v1.50.1
google.golang.org/protobuf v1.28.1
)

require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect
golang.org/x/text v0.3.3 // indirect
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
)
Loading

0 comments on commit 9d4b03a

Please sign in to comment.