parent
99ce1db7bb
commit
07994fed98
@ -1,3 +1,4 @@
|
|||||||
gtunnel*
|
gtunnel*
|
||||||
*~
|
*~
|
||||||
*bak
|
*bak
|
||||||
|
*swp
|
||||||
|
@ -1,37 +1,22 @@
|
|||||||
gtunnel
|
gtunnel
|
||||||
======
|
======
|
||||||
|
|
||||||
A stunnel like util write by golang
|
A stunnel-like util write by golang
|
||||||
|
|
||||||
There are two work mode.
|
work mode
|
||||||
|
========
|
||||||
|
|
||||||
###Client mode
|
- listen plain, forward through plain
|
||||||
|
- listen plain, forward through TLS
|
||||||
|
- listen TLS, forward through plain
|
||||||
|
- listen TLS, forward through TLS
|
||||||
|
|
||||||
In this mode, listen for incoming plain connections and forward to server to use SSL/TLS connections
|
|
||||||
|
|
||||||
###Server mode
|
usage
|
||||||
|
====
|
||||||
In this mode, listen for incoming SSL/TLS connections and forward to backend use plain connections
|
|
||||||
|
|
||||||
###Build
|
|
||||||
|
|
||||||
go get github.com/fangdingjun/gtunnel
|
go get github.com/fangdingjun/gtunnel
|
||||||
cd $GOPATH/src/github.com/fangdingjun/gtunnel
|
cp $GOPATH/src/github.com/fangdingjun/config_example.yaml config.yaml
|
||||||
go build
|
vim config.yaml
|
||||||
|
$GOPATH/bin/gtunnel -c config.yaml
|
||||||
###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
|
|
||||||
|
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConf(t *testing.T) {
|
||||||
|
c, err := loadConfig("config_example.yaml")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%#v\n", c)
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
//"fmt"
|
||||||
|
"github.com/go-yaml/yaml"
|
||||||
|
"io/ioutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
type server struct {
|
||||||
|
Listen listen
|
||||||
|
Backend backend
|
||||||
|
}
|
||||||
|
|
||||||
|
type conf []server
|
||||||
|
|
||||||
|
type listen struct {
|
||||||
|
Host string
|
||||||
|
Port int
|
||||||
|
Cert string
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
type backend struct {
|
||||||
|
Host string
|
||||||
|
Port int
|
||||||
|
Hostname string
|
||||||
|
TLS bool
|
||||||
|
Insecure bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadConfig(fn string) (*conf, error) {
|
||||||
|
data, err := ioutil.ReadFile(fn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c := new(conf)
|
||||||
|
err = yaml.Unmarshal(data, c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
# gtunnel can do the follow things
|
||||||
|
# a. listen plain, forward through TLS
|
||||||
|
# b. listen plain, forward through plain
|
||||||
|
# c. listen TLS, forward through plain
|
||||||
|
# d. listen TLS, forward through TLS
|
||||||
|
#
|
||||||
|
# when cert and key specified it will listen on TLS
|
||||||
|
#
|
||||||
|
|
||||||
|
-
|
||||||
|
# listen plain and forward through TLS
|
||||||
|
listen:
|
||||||
|
host: 0.0.0.0
|
||||||
|
port: 4120
|
||||||
|
|
||||||
|
backend:
|
||||||
|
host: 1.2.3.4
|
||||||
|
port: 443
|
||||||
|
|
||||||
|
# tls sni
|
||||||
|
hostname: example.com
|
||||||
|
|
||||||
|
# use TLS
|
||||||
|
tls: true
|
||||||
|
|
||||||
|
# verify server certificate or not
|
||||||
|
# when set true, will not verify the server's certificate(danger)
|
||||||
|
insecure: false
|
||||||
|
|
||||||
|
-
|
||||||
|
# listen tls and forward through plain
|
||||||
|
listen:
|
||||||
|
host: 0.0.0.0
|
||||||
|
port: 443
|
||||||
|
cert: www.crt
|
||||||
|
key: www.key
|
||||||
|
|
||||||
|
backend:
|
||||||
|
host: 127.0.0.1
|
||||||
|
port: 4120
|
||||||
|
tls: false
|
||||||
|
|
||||||
|
# more port forwards
|
||||||
|
|
||||||
|
#-
|
||||||
|
# # listen TLS, forward through TLS
|
||||||
|
# listen:
|
||||||
|
# host: 0.0.0.0
|
||||||
|
# port: 3122
|
||||||
|
# cert: file.crt
|
||||||
|
# key: file.key
|
||||||
|
#
|
||||||
|
# backend:
|
||||||
|
# host: www.example.com
|
||||||
|
# port: 443
|
||||||
|
# hostname: example.com
|
||||||
|
# tls: true
|
@ -1,53 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,39 +1,111 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"flag"
|
"flag"
|
||||||
"github.com/fangdingjun/iniflags"
|
"fmt"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
var remote string
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var server, client bool
|
var configfile string
|
||||||
flag.StringVar(&remote, "remote", "", "remote server")
|
|
||||||
flag.IntVar(&port, "port", 8080, "the listen port")
|
flag.StringVar(&configfile, "c", "config.yaml", "config file")
|
||||||
flag.BoolVar(&server, "server", false, "tls server mode")
|
flag.Parse()
|
||||||
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 == "" {
|
cfg, err := loadConfig(configfile)
|
||||||
log.Fatal("please use --remote to special the server")
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if server {
|
initServer(cfg)
|
||||||
if cert == "" || key == "" {
|
|
||||||
log.Fatal("in server mode, you must special the certificate and private key")
|
select {}
|
||||||
}
|
}
|
||||||
server_main()
|
|
||||||
return
|
func initServer(cfg *conf) {
|
||||||
|
for _, srv := range *cfg {
|
||||||
|
go initListener(srv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initListener(srv server) {
|
||||||
|
var l net.Listener
|
||||||
|
var err error
|
||||||
|
|
||||||
|
host := net.JoinHostPort(srv.Listen.Host, fmt.Sprintf("%d", srv.Listen.Port))
|
||||||
|
|
||||||
|
if srv.Listen.Cert != "" && srv.Listen.Key != "" {
|
||||||
|
cert, err := tls.LoadX509KeyPair(srv.Listen.Cert, srv.Listen.Key)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
config := &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err = tls.Listen("tcp", host, config)
|
||||||
|
} else {
|
||||||
|
l, err = net.Listen("tcp", host)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if client {
|
for {
|
||||||
local_main()
|
conn, err := l.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
go handleConn(conn, srv.Backend)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleConn(conn net.Conn, b backend) {
|
||||||
|
var c net.Conn
|
||||||
|
var err error
|
||||||
|
|
||||||
|
host := net.JoinHostPort(b.Host, fmt.Sprintf("%d", b.Port))
|
||||||
|
if b.TLS {
|
||||||
|
hostname := b.Host
|
||||||
|
if b.Hostname != "" {
|
||||||
|
hostname = b.Hostname
|
||||||
|
}
|
||||||
|
config := &tls.Config{
|
||||||
|
ServerName: hostname,
|
||||||
|
InsecureSkipVerify: b.Insecure,
|
||||||
|
}
|
||||||
|
c, err = tls.Dial("tcp", host, config)
|
||||||
|
} else {
|
||||||
|
c, err = net.Dial("tcp", host)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Fatal("please use --server or --client to special a work mode")
|
pipeAndClose(conn, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pipeAndClose(c1, c2 net.Conn) {
|
||||||
|
defer c1.Close()
|
||||||
|
defer c2.Close()
|
||||||
|
|
||||||
|
ch := make(chan struct{}, 2)
|
||||||
|
go func() {
|
||||||
|
io.Copy(c1, c2)
|
||||||
|
ch <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
io.Copy(c2, c1)
|
||||||
|
ch <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
|
<-ch
|
||||||
}
|
}
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
Loading…
Reference in New Issue