From 6ab42b01fd63aa277f0ce2786b81edde2625c078 Mon Sep 17 00:00:00 2001 From: fangdingjun Date: Tue, 19 Jan 2016 11:13:57 +0800 Subject: [PATCH] Initial commit --- .gitignore | 3 +++ README.md | 41 +++++++++++++++++++++++++++++++++++++ local.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++ main.go | 39 +++++++++++++++++++++++++++++++++++ server.go | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 196 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 local.go create mode 100644 main.go create mode 100644 server.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d5cdd8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +gtunnel* +*~ +*bak diff --git a/README.md b/README.md new file mode 100644 index 0000000..2d10043 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +gtunnel +====== + +A stunnel like util write by golang + +There are two work mode. + +Client mode +========== + +In this mode, listen for incoming plain connections and forward to server to use SSL/TLS connections + +Server mode +=========== + +In this mode, listen for incoming SSL/TLS connections and forward to backend use plain connections + +Build +==== + + go get github.com/fangdingjun/gtunnel + cd $GOPATH/src/github.com/fangdingjun/gtunnel + go build + +Usage +==== + +server mode + + ./gtunnel --server --cert server.crt --key server.key --port 8001 --remote 127.0.0.1:80 + +listen for SSL/TLS connections on port 8001 and forward to 127.0.0.1:80 + +client mode + + ./gtunnel --client --port 8002 --remote www.example.com:8081 + +listen for plain connections on port 8002 and forward to www.example.com:8081 to use SSL/TLS connections + +use `./gtunnel -h` see more options + diff --git a/local.go b/local.go new file mode 100644 index 0000000..7a4e64e --- /dev/null +++ b/local.go @@ -0,0 +1,53 @@ +package main + +import ( + "crypto/tls" + "fmt" + "io" + "log" + "net" +) + +//var server string = "www.ratafee.nl:443" + +func local_main() { + l, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err != nil { + log.Fatal(err) + } + log.Printf("Listen on %s...", l.Addr()) + defer l.Close() + + for { + c, err := l.Accept() + if err != nil { + log.Println(err) + continue + } + go handle_local(c) + } +} + +func handle_local(c net.Conn) { + //defer c.Close() + log.Printf("accept connection from %s", c.RemoteAddr()) + log.Printf("connect to %s...", remote) + s, err := tls.Dial("tcp", remote, nil) + if err != nil { + log.Printf("connect to %s failed: %s", remote, err.Error()) + c.Close() + return + } + ch := make(chan int) + //defer s.Close() + go func() { + count, _ := io.Copy(s, c) + log.Printf("write %d bytes to %s", count, s.RemoteAddr()) + s.Close() + ch <- 1 + }() + co, _ := io.Copy(c, s) + log.Printf("write %d bytes to %s", co, c.RemoteAddr()) + c.Close() + <-ch +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..836834b --- /dev/null +++ b/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "flag" + "github.com/fangdingjun/iniflags" + "log" +) + +var remote string + +func main() { + var server, client bool + flag.StringVar(&remote, "remote", "", "remote server") + flag.IntVar(&port, "port", 8080, "the listen port") + flag.BoolVar(&server, "server", false, "tls server mode") + flag.BoolVar(&client, "client", false, "tls client mode") + flag.StringVar(&cert, "cert", "", "the certificate file") + flag.StringVar(&key, "key", "", "the private key") + iniflags.Parse() + + if remote == "" { + log.Fatal("please use --remote to special the server") + } + + if server { + if cert == "" || key == "" { + log.Fatal("in server mode, you must special the certificate and private key") + } + server_main() + return + } + + if client { + local_main() + return + } + + log.Fatal("please use --server or --client to special a work mode") +} diff --git a/server.go b/server.go new file mode 100644 index 0000000..df2b59a --- /dev/null +++ b/server.go @@ -0,0 +1,60 @@ +package main + +import ( + "crypto/tls" + "fmt" + "io" + "log" + "net" +) + +//var backend = "127.0.0.1:8080" +var cert = "server.crt" +var key = "server.key" +var port = 9000 + +func server_main() { + certificate, err := tls.LoadX509KeyPair(cert, key) + if err != nil { + log.Fatal(err) + } + l, err := tls.Listen("tcp", fmt.Sprintf(":%d", port), &tls.Config{ + Certificates: []tls.Certificate{certificate}, + }) + if err != nil { + log.Fatal(err) + } + defer l.Close() + + for { + c, err := l.Accept() + if err != nil { + log.Println(err) + continue + } + go handle_server(c) + } +} + +func handle_server(c net.Conn) { + log.Printf("accept connection from %s", c.RemoteAddr()) + s, err := net.Dial("tcp", remote) + if err != nil { + log.Println(err) + c.Close() + return + } + + ch := make(chan int) + go func() { + count, _ := io.Copy(s, c) + s.Close() + log.Printf("write %d bytes to %s", count, s.RemoteAddr()) + ch <- 1 + }() + + co, _ := io.Copy(c, s) + c.Close() + log.Printf("write %d bytes to %s", co, c.RemoteAddr()) + <-ch +}