-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathgosecure.go
171 lines (137 loc) · 3.56 KB
/
gosecure.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package main
import (
"crypto/tls"
"flag"
"fmt"
"io"
"log"
"net"
"os"
"strings"
"sync"
_ "gosecure/internal/logger"
)
// Config : Command line arguments
type Config struct {
certfile string
keyfile string
local string
remote string
mintls string
alpn string
}
// This three values are changed from Makefile
var (
// BINARY_NAME : Executable binary name
BINARY_NAME = "gosecure"
// VERSION : Running version
VERSION = "v0.0.1"
// VERSION_NAME : Version code name
VERSION_NAME = "Tunelito"
)
// CONFIG : Command line arguments instance
var (
CONFIG Config
tlsConfig *tls.Config
)
func init() {
os.Setenv("GODEBUG", os.Getenv("GODEBUG")+",tls13=1")
}
func main() {
//log.SetFlags(log.Lshortfile)
flag.StringVar(&CONFIG.certfile, "cert", "", "Certificate file")
flag.StringVar(&CONFIG.keyfile, "key", "", "Key file")
flag.StringVar(&CONFIG.local, "local", "", "Where to listen on this machine [ip_address]:port")
flag.StringVar(&CONFIG.remote, "remote", "", "Where to connect to {ip_address | hostname}:port")
flag.StringVar(&CONFIG.mintls, "min-tls", "1.3", "Minimum TLS version accepted")
flag.StringVar(&CONFIG.alpn, "alpn", "", "Comma-separated list of supported application level protocols")
flag.Parse()
if CONFIG.certfile == "" || CONFIG.keyfile == "" || CONFIG.local == "" || CONFIG.remote == "" {
fmt.Printf("%s v%s (%s)\n\n", BINARY_NAME, VERSION, VERSION_NAME)
flag.PrintDefaults()
os.Exit(1)
}
mintls := tls.VersionTLS13
switch CONFIG.mintls {
case "1.0":
mintls = tls.VersionTLS10
case "1.1":
mintls = tls.VersionTLS11
case "1.2":
mintls = tls.VersionTLS12
default:
mintls = tls.VersionTLS13
}
log.Printf("Starting %s v%s (%s)\n", BINARY_NAME, VERSION, VERSION_NAME)
cer, err := tls.LoadX509KeyPair(CONFIG.certfile, CONFIG.keyfile)
if err != nil {
log.Println(err)
return
}
tlsConfig = &tls.Config{
Certificates: []tls.Certificate{cer},
MinVersion: uint16(mintls),
NextProtos: strings.Split(CONFIG.alpn, ","),
}
//ln, err := tls.Listen("tcp", CONFIG.local, tlsConfig)
ln, err := net.Listen("tcp", CONFIG.local)
if err != nil {
log.Println(err)
return
}
defer ln.Close()
for {
conn, err := ln.Accept()
if err != nil {
log.Println(err)
continue
}
go handleConnection(conn)
}
}
func handleConnection(c net.Conn) {
var iconn net.Conn
defer c.Close()
logprefix := fmt.Sprintf("%s -> %s ::", c.RemoteAddr(), CONFIG.remote)
log.Println(logprefix, "Starting tunnel")
log.Println(logprefix, "Connecting to", CONFIG.remote)
oconn, err := net.Dial("tcp", CONFIG.remote)
if err != nil {
log.Println(logprefix, err)
return
}
defer oconn.Close()
tlsConn := tls.Server(c, tlsConfig)
err = tlsConn.Handshake()
if err != nil {
if tlsErr, ok := err.(tls.RecordHeaderError); ok {
//oconn.Write(tlsErr.RecordHeader[:])
iconn = tlsErr.Conn
} else {
log.Println(logprefix, "tls error:", tlsErr.Error())
}
} else {
iconn = tlsConn
}
log.Println(logprefix, "Connected to", CONFIG.remote)
wg := &sync.WaitGroup{}
wg.Add(2)
log.Println(logprefix, "Connecting wires")
go cp(oconn, iconn, wg)
go cp(iconn, oconn, wg)
log.Println(logprefix, "Waiting wires to cut")
wg.Wait()
log.Println(logprefix, "Wires cut")
}
func cp(from, to net.Conn, wg *sync.WaitGroup) {
defer wg.Done()
logprefix := fmt.Sprintf("%s -> %s ::", from.RemoteAddr(), to.RemoteAddr())
log.Println(logprefix, "Starting cp")
bc, err := io.Copy(to, from)
if err != nil {
log.Println(logprefix, err)
}
log.Println(logprefix, "::", bc, "bytes")
to.Close()
log.Println(logprefix + "::Exiting cp")
}