Skip to content

Commit 95e9b09

Browse files
committed
add native TLS support and modernize software packaging
1 parent e61db5c commit 95e9b09

12 files changed

Lines changed: 156 additions & 73 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
tcpsplice
2-
monitor.go
2+
static.go
33
debian/tcpsplice
44
debian/*debhelper*
55
debian/*substvars*

Makefile

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
#!/bin/sh
22

3-
tcpsplice: *.go monitor.html
4-
@(echo -n "package main\nimport \"encoding/base64\"\nconst _monitorContent = \""; base64 -w 0 < monitor.html; echo "\"\nvar monitorContent []byte\nfunc init() { monitorContent, _ = base64.StdEncoding.DecodeString(_monitorContent) }") >monitor.go
5-
@export GOPATH=/tmp/go; export CGO_ENABLED=0; go build -trimpath -o tcpsplice && strip tcpsplice
3+
# build targets
4+
tcpsplice: static.go main.go
5+
@env GOPATH=/tmp/go CGO_ENABLED=0 go build -trimpath -o tcpsplice
6+
@-strip tcpsplice 2>/dev/null || true
7+
@-upx -9 tcpsplice 2>/dev/null || true
8+
static.go: rpack
9+
@-./rpack static
10+
rpack:
11+
@-env GOBIN=`pwd` go get github.com/pyke369/golang-support/rpack/rpack
612
clean:
713
distclean:
8-
@rm -rf tcpsplice monitor.go
14+
@rm -rf tcpsplice static.go rpack
915
deb:
1016
@debuild -e GOROOT -e GOPATH -e PATH -i -us -uc -b
1117
debclean:
1218
@debuild -- clean
1319
@rm -f ../tcpsplice_*
1420

21+
# run targets
1522
run: tcpsplice
16-
@./tcpsplice tcpsplice.conf
23+
@./tcpsplice conf/tcpsplice.conf

conf/cert.pem

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIICuDCCAaCgAwIBAgIJALltl03a8TCpMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
3+
BAMTCWxvY2FsaG9zdDAeFw0xNjEwMTAxODQwNTdaFw0yNjEwMDgxODQwNTdaMBQx
4+
EjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
5+
ggEBAKfI4D4LtZrfnujBiOQ13PItpS5ZGzAr0DxUVGvKviaqGJcFjUPikydkVayJ
6+
fPoaZR4WZVL9ThqXQSctMnK16WO3U+6G5srnTHtKS7YPnuOEhBFJsAF7955cUGaY
7+
ShU3eeKG9lkws/W3tdd8WsgDSIfBJ3mCCzfQaaWtD/zGxe4pCAW9x5IOKFby4+Sk
8+
0QbAfx1Ngi1Czj1Uw3En8yvQphm8A0C8kXrGhDd1lUdPYHWcHCBlflLKMsLAdK2C
9+
Rr+wfrhbTCZnULXN/K7/p4gthFIzajb//fuK4rQoTWfIeaaNUtZ3/Kahnw62MK/6
10+
Yg0ZNGDYPdz53z7AVLrAMh0u+tMCAwEAAaMNMAswCQYDVR0TBAIwADANBgkqhkiG
11+
9w0BAQsFAAOCAQEANaDuPI/UOSmZxEWnYZ9olS9jW5pKHGmIkjAdHANotj47W4QX
12+
vfVR6/JKSLAvWMDKlUdtbfe1qSdY+GRZHyLPI0dcVZq8fO5Vmc+D9rCkPR8Iy1Lq
13+
NbYo5uFfn1ZoaXO7ex6dcyn9li+ex0G8lj7mR5EB/R0wd9E4ClZOnWGt43C90PwN
14+
1lBzNGn/H3cGq6xaOK+pfx7aIPsnWwnPwgwWSDojJt4ayBJ+JnSGszOGtVjgKBl7
15+
NciXESNkm8bSDVvebVNtmj//Vu04KaO2bRCM/PAqPyy3zwrzvZ3dzqUDWzJ1EB94
16+
0sULH3G24rkQp3M9BTDANVNFTmnr9gD/8lZlxQ==
17+
-----END CERTIFICATE-----

conf/key.pem

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCnyOA+C7Wa357o
3+
wYjkNdzyLaUuWRswK9A8VFRryr4mqhiXBY1D4pMnZFWsiXz6GmUeFmVS/U4al0En
4+
LTJyteljt1PuhubK50x7Sku2D57jhIQRSbABe/eeXFBmmEoVN3nihvZZMLP1t7XX
5+
fFrIA0iHwSd5ggs30GmlrQ/8xsXuKQgFvceSDihW8uPkpNEGwH8dTYItQs49VMNx
6+
J/Mr0KYZvANAvJF6xoQ3dZVHT2B1nBwgZX5SyjLCwHStgka/sH64W0wmZ1C1zfyu
7+
/6eILYRSM2o2//37iuK0KE1nyHmmjVLWd/ymoZ8OtjCv+mINGTRg2D3c+d8+wFS6
8+
wDIdLvrTAgMBAAECggEAVAQ5jbgtUwUhPKoU0znJjpeevCuwepml51/O+j8GorPQ
9+
JmeISnL9ft82K3SZWV+4PK24RStEXfpZjLWMKna/DMizRaDVlsrluGMGsH738DPe
10+
Mg31DXk3EFxngkhF6IPkC7PLTfQeWS+J5gKGLtu+CQSGsMiWt3csP+L+O3SJjmy7
11+
yn/uu2HwqpgUG9BpiG4yFjGXmefvUP0o/LGa+TzIIojlpWl7dGBzNJ12bi+0Dpq7
12+
Ztv/xJFxA+2RBkRVHSMIyVopdtWNWl09adZjDWZY2muMEWEf0kogOKD8tvJ5Eru5
13+
aMGH2/H4Fq26AKDpeS9BjQ61VmRFWr66WqCNVaq/4QKBgQDVY89lEB4Q10AUcKRB
14+
v9dFX9KIcBfNqcKHELq5tthUFYqj/IyWIZ5GvAtgIO3yZ92EYW7g1WRz1rF37XIn
15+
GafIk8m34Wq9+RJNc+hoPDRB/RTq5c97blUOl6FBhG/o35Wsr4N7jT844amSGZ/A
16+
ct07yxgQWTIF4qQayFRnvUNyAwKBgQDJScqttoSeiu8E/7gIWODj5ZBF/vq8m74n
17+
nKr6e2RZ6okhT0l52wK4rh91rGHdZoEJTE+0IZh4VlcjOarbpx//YcJCAHzDSlBM
18+
yJ93Xu8zrTH64gitZfrzoPPvhFaPgQrShwHawhwm//BCFQ5MnpLZ2uMxUh+kQmfm
19+
x4xj+K7i8QKBgQDO02P0P6/0gL1SUm9Sbv/W9O5ZYdQgedbbFML3OBrrPMnY8fLN
20+
nR4MzzxzWtdmqXdSVSGj+BDaGhB+/f0zmrE+Psg4Wtsb8KrluV9ckGXSQ9ufZUk6
21+
CJGWiC87EoNpgjRPYPqeqSPLHSY/PmjRnkOCLfJP/jP28lo+v0bYGeCiQwKBgGFm
22+
M4ybJNESqVXh50sitq+QBZ/ZIbriIcFJLfLGgmh/9JsJoqQ0NbznhJGMOE7Jqua0
23+
5lxjZUPVg5Sn8uUWmYUZ6MXHNpfI/dIpwgAhD94RkH21oj1Fe4kn+OGNR9Vou7Pj
24+
YCJaiwTUE43mYmTw1l5UbFsRQf5Zo60oIea+DuIBAoGBAJuiSHfXlv9OdlLghiFk
25+
XJs4spEqeAS+nfx2BScT2ft4MC5x0cUPovQ6AL/6YBCk+LDKqYn4UM4Aez5rnPPV
26+
FqQXXmeGQndRvBrLb1tnviTi+uU8pGI/H5hiAC3B8nJKq8VlmBH34fKIuBR2Iuil
27+
P85Yr82Fr8w1deA5U9Ear+gf
28+
-----END PRIVATE KEY-----

conf/tcpsplice.conf

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
server
2+
{
3+
// log = "console()"
4+
}
5+
6+
monitor
7+
{
8+
listen = "*:8000"
9+
# acl
10+
# {
11+
# allow = [ "127.0.0.1" ]
12+
# auth = [ "tcpsplice:monitor" ]
13+
# }
14+
}
15+
16+
services
17+
{
18+
rtmp
19+
{
20+
local = [ "*:1935" ]
21+
remote = [ "my.server.com:1935" ]
22+
// connect_timeout = 10
23+
// write_timeout = 10
24+
// idle_timeout = 60
25+
// incoming_buffer_size = 64k
26+
// outgoing_buffer_size = 64k
27+
// log_minimum_size = 1k
28+
// session_minimum_size = 1k
29+
// meta_size = 16k
30+
// meta_scan = "["
31+
}
32+
33+
rtmps
34+
{
35+
local = [ "*:1936,conf/cert.pem,conf/key.pem" ]
36+
remote = [ "my.server.com:1935" ]
37+
// connect_timeout = 10
38+
// write_timeout = 10
39+
// idle_timeout = 60
40+
// incoming_buffer_size = 64k
41+
// outgoing_buffer_size = 64k
42+
// log_minimum_size = 1k
43+
// session_minimum_size = 1k
44+
// meta_size = 16k
45+
// meta_scan = "["
46+
}
47+
}

debian/changelog

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
tcpsplice (1.2.0) stable; urgency=medium
2+
3+
* add native TLS support and modernize software packaging
4+
5+
-- Pierre-Yves Kerembellec <py.kerembellec@gmail.com> Thu, 11 Feb 2021 16:45:09 +0100
6+
17
tcpsplice (1.1.0) stable; urgency=medium
28

39
* update to Go 1.15 (and Go modules)

debian/install

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
tcpsplice usr/bin
2-
tcpsplice.conf etc
2+
conf/tcpsplice.conf etc

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
module tcpsplice
1+
module main
22

33
go 1.15
44

5-
require github.com/pyke369/golang-support v0.0.0-20200321184731-cd1ed731523d
5+
require github.com/pyke369/golang-support v0.0.0-20210211171524-9d13f1802e2b

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
github.com/pyke369/golang-support v0.0.0-20200321184731-cd1ed731523d h1:bssjYWDUaYbjtBc7gZ6BI3YBerIg5EAn+kAM5hMQf2s=
2-
github.com/pyke369/golang-support v0.0.0-20200321184731-cd1ed731523d/go.mod h1:0XGrzgrEp0fa/+JSV8XZePUwyjnU6C3bMc7Xz2bHHKI=
1+
github.com/pyke369/golang-support v0.0.0-20210211171524-9d13f1802e2b h1:XamoXfiYhBSPMo9+rf5BIG0fmFzpoSyLUqsXTnnhydk=
2+
github.com/pyke369/golang-support v0.0.0-20210211171524-9d13f1802e2b/go.mod h1:0XGrzgrEp0fa/+JSV8XZePUwyjnU6C3bMc7Xz2bHHKI=

main.go

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ package main
22

33
import (
44
"crypto/md5"
5+
"crypto/tls"
56
"encoding/json"
67
"fmt"
7-
"github.com/pyke369/golang-support/uconfig"
8-
"github.com/pyke369/golang-support/ulog"
98
"math"
109
"math/rand"
1110
"net"
@@ -16,10 +15,14 @@ import (
1615
"strings"
1716
"sync"
1817
"time"
18+
19+
"github.com/pyke369/golang-support/dynacert"
20+
"github.com/pyke369/golang-support/uconfig"
21+
"github.com/pyke369/golang-support/ulog"
1922
)
2023

2124
const progname = "tcpsplice"
22-
const version = "1.1.0"
25+
const version = "1.2.0"
2326

2427
type Session struct {
2528
id, service, source, target, meta string
@@ -40,9 +43,9 @@ var (
4043
sessionsLock sync.RWMutex
4144
)
4245

43-
func serviceHandler(service string, listener *net.TCPListener) {
46+
func serviceHandler(service string, listener net.Listener) {
4447
for {
45-
if source, err := listener.AcceptTCP(); err == nil {
48+
if source, err := listener.Accept(); err == nil {
4649
remotes := config.GetPaths(fmt.Sprintf("services.%s.remote", service))
4750
if len(remotes) > 0 {
4851
go func() {
@@ -57,8 +60,10 @@ func serviceHandler(service string, listener *net.TCPListener) {
5760
idleTimeout := time.Second * time.Duration(config.GetDurationBounds(fmt.Sprintf("services.%s.idle_timeout", service), 60, 0, 300))
5861
metaSize := int(config.GetSizeBounds(fmt.Sprintf("services.%s.meta_size", service), 16*1024, 0, 64*1024))
5962
metaScan, _ := regexp.Compile(config.GetString(fmt.Sprintf("services.%s.meta_scan", service), "["))
60-
source.SetReadBuffer(int(incomingSize))
61-
source.SetWriteBuffer(int(incomingSize))
63+
if tsource, ok := source.(*net.TCPConn); ok {
64+
tsource.SetReadBuffer(int(incomingSize))
65+
tsource.SetWriteBuffer(int(incomingSize))
66+
}
6267
target.(*net.TCPConn).SetReadBuffer(int(outgoingSize))
6368
target.(*net.TCPConn).SetWriteBuffer(int(outgoingSize))
6469
session := &Session{
@@ -208,23 +213,25 @@ func monitorHandler(response http.ResponseWriter, request *http.Request) {
208213
services := map[string]interface{}{}
209214
for _, service := range config.GetPaths("services") {
210215
service = strings.TrimPrefix(service, "services.")
211-
s := map[string]interface{}{}
216+
entries := map[string]interface{}{}
212217
sessionsLock.RLock()
213218
for id, session := range sessions {
214-
s[id] = map[string]interface{}{
215-
"started": session.started.Unix(),
216-
"duration": time.Now().Sub(session.started) / time.Second,
217-
"source": session.source,
218-
"target": session.target,
219-
"bytes": [2]int64{session.sourceRead, session.targetRead},
220-
"mean": [2]float64{session.sourceMeanThroughput, session.targetMeanThroughput},
221-
"last": [2]float64{session.sourceLastThroughput, session.targetLastThroughput},
222-
"meta": session.meta,
223-
"done": session.done,
219+
if session.service == service {
220+
entries[id] = map[string]interface{}{
221+
"started": session.started.Unix(),
222+
"duration": time.Now().Sub(session.started) / time.Second,
223+
"source": session.source,
224+
"target": session.target,
225+
"bytes": [2]int64{session.sourceRead, session.targetRead},
226+
"mean": [2]float64{session.sourceMeanThroughput, session.targetMeanThroughput},
227+
"last": [2]float64{session.sourceLastThroughput, session.targetLastThroughput},
228+
"meta": session.meta,
229+
"done": session.done,
230+
}
224231
}
225232
}
226233
sessionsLock.RUnlock()
227-
services[service] = s
234+
services[service] = entries
228235
}
229236
output["services"] = services
230237
response.Header().Set("Content-Type", "application/json")
@@ -242,9 +249,6 @@ func monitorHandler(response http.ResponseWriter, request *http.Request) {
242249
}
243250
}
244251
sessionsLock.RUnlock()
245-
} else {
246-
response.Header().Set("Content-Type", "text/html; charset=utf-8")
247-
response.Write(monitorContent)
248252
}
249253
}
250254

@@ -315,21 +319,27 @@ func main() {
315319
for _, service := range config.GetPaths("services") {
316320
for _, local := range config.GetPaths(fmt.Sprintf("%s.local", service)) {
317321
service = strings.TrimPrefix(service, "services.")
318-
local = config.GetString(local, "")
319-
if address, err := net.ResolveTCPAddr("tcp", strings.TrimLeft(local, "*")); err == nil {
320-
if listener, err := net.ListenTCP("tcp", address); err == nil {
321-
logger.Info(map[string]interface{}{"type": "service", "name": service, "listen": local})
322+
if parts := strings.Split(config.GetStringMatch(local, "_", "^.*?(:\\d+)?((,[^,]+){2})?$"), ","); parts[0] != "_" {
323+
if listener, err := net.Listen("tcp", strings.TrimLeft(parts[0], "*")); err == nil {
324+
if len(parts) > 1 {
325+
loader := &dynacert.DYNACERT{Public: parts[1], Key: parts[2]}
326+
listener = tls.NewListener(listener, dynacert.IntermediateTLSConfig(loader.GetCertificate))
327+
logger.Info(map[string]interface{}{"type": "service", "name": service, "listen": parts[0], "cert": parts[1], "key": parts[2]})
328+
} else {
329+
logger.Info(map[string]interface{}{"type": "service", "name": service, "listen": parts[0]})
330+
}
322331
go serviceHandler(service, listener)
323332
} else {
324-
logger.Warn(map[string]interface{}{"type": "service", "name": service, "listen": local, "error": err})
333+
logger.Warn(map[string]interface{}{"type": "service", "name": service, "listen": parts[0], "error": err})
325334
}
326-
} else {
327-
logger.Warn(map[string]interface{}{"type": "service", "name": service, "listen": local, "error": err})
328335
}
329336
}
330337
}
331338

332-
http.Handle("/", baseHandler(http.HandlerFunc(monitorHandler)))
339+
http.Handle("/sessions.json", baseHandler(http.HandlerFunc(monitorHandler)))
340+
http.Handle("/abort/", baseHandler(http.HandlerFunc(monitorHandler)))
341+
http.Handle("/", baseHandler(http.StripPrefix("/", Resources(6*time.Hour))))
342+
333343
if parts := strings.Split(config.GetStringMatch("monitor.listen", "_", "^(?:\\*|\\d+(?:\\.\\d+){3}|\\[[^\\]]+\\])(?::\\d+)?(?:(?:,[^,]+){2})?$"), ","); parts[0] != "_" {
334344
server := &http.Server{Addr: strings.TrimLeft(parts[0], "*")}
335345
if len(parts) > 1 {

0 commit comments

Comments
 (0)