Skip to content

Commit

Permalink
add native TLS support and modernize software packaging
Browse files Browse the repository at this point in the history
  • Loading branch information
pyke369 committed Feb 11, 2021
1 parent e61db5c commit cbc314f
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 72 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
tcpsplice
monitor.go
static.go
debian/tcpsplice
debian/*debhelper*
debian/*substvars*
Expand Down
17 changes: 12 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
#!/bin/sh

tcpsplice: *.go monitor.html
@(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
@export GOPATH=/tmp/go; export CGO_ENABLED=0; go build -trimpath -o tcpsplice && strip tcpsplice
# build targets
tcpsplice: static.go main.go
@env GOPATH=/tmp/go CGO_ENABLED=0 go build -trimpath -o tcpsplice
@-strip tcpsplice 2>/dev/null || true
@-upx -9 tcpsplice 2>/dev/null || true
static.go: rpack
@-./rpack static
rpack:
@-env GOBIN=`pwd` go get github.com/pyke369/golang-support/rpack/rpack
clean:
distclean:
@rm -rf tcpsplice monitor.go
@rm -rf tcpsplice static.go rpack
deb:
@debuild -e GOROOT -e GOPATH -e PATH -i -us -uc -b
debclean:
@debuild -- clean
@rm -f ../tcpsplice_*

# run targets
run: tcpsplice
@./tcpsplice tcpsplice.conf
@./tcpsplice conf/tcpsplice.conf
17 changes: 17 additions & 0 deletions conf/cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICuDCCAaCgAwIBAgIJALltl03a8TCpMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
BAMTCWxvY2FsaG9zdDAeFw0xNjEwMTAxODQwNTdaFw0yNjEwMDgxODQwNTdaMBQx
EjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAKfI4D4LtZrfnujBiOQ13PItpS5ZGzAr0DxUVGvKviaqGJcFjUPikydkVayJ
fPoaZR4WZVL9ThqXQSctMnK16WO3U+6G5srnTHtKS7YPnuOEhBFJsAF7955cUGaY
ShU3eeKG9lkws/W3tdd8WsgDSIfBJ3mCCzfQaaWtD/zGxe4pCAW9x5IOKFby4+Sk
0QbAfx1Ngi1Czj1Uw3En8yvQphm8A0C8kXrGhDd1lUdPYHWcHCBlflLKMsLAdK2C
Rr+wfrhbTCZnULXN/K7/p4gthFIzajb//fuK4rQoTWfIeaaNUtZ3/Kahnw62MK/6
Yg0ZNGDYPdz53z7AVLrAMh0u+tMCAwEAAaMNMAswCQYDVR0TBAIwADANBgkqhkiG
9w0BAQsFAAOCAQEANaDuPI/UOSmZxEWnYZ9olS9jW5pKHGmIkjAdHANotj47W4QX
vfVR6/JKSLAvWMDKlUdtbfe1qSdY+GRZHyLPI0dcVZq8fO5Vmc+D9rCkPR8Iy1Lq
NbYo5uFfn1ZoaXO7ex6dcyn9li+ex0G8lj7mR5EB/R0wd9E4ClZOnWGt43C90PwN
1lBzNGn/H3cGq6xaOK+pfx7aIPsnWwnPwgwWSDojJt4ayBJ+JnSGszOGtVjgKBl7
NciXESNkm8bSDVvebVNtmj//Vu04KaO2bRCM/PAqPyy3zwrzvZ3dzqUDWzJ1EB94
0sULH3G24rkQp3M9BTDANVNFTmnr9gD/8lZlxQ==
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions conf/key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCnyOA+C7Wa357o
wYjkNdzyLaUuWRswK9A8VFRryr4mqhiXBY1D4pMnZFWsiXz6GmUeFmVS/U4al0En
LTJyteljt1PuhubK50x7Sku2D57jhIQRSbABe/eeXFBmmEoVN3nihvZZMLP1t7XX
fFrIA0iHwSd5ggs30GmlrQ/8xsXuKQgFvceSDihW8uPkpNEGwH8dTYItQs49VMNx
J/Mr0KYZvANAvJF6xoQ3dZVHT2B1nBwgZX5SyjLCwHStgka/sH64W0wmZ1C1zfyu
/6eILYRSM2o2//37iuK0KE1nyHmmjVLWd/ymoZ8OtjCv+mINGTRg2D3c+d8+wFS6
wDIdLvrTAgMBAAECggEAVAQ5jbgtUwUhPKoU0znJjpeevCuwepml51/O+j8GorPQ
JmeISnL9ft82K3SZWV+4PK24RStEXfpZjLWMKna/DMizRaDVlsrluGMGsH738DPe
Mg31DXk3EFxngkhF6IPkC7PLTfQeWS+J5gKGLtu+CQSGsMiWt3csP+L+O3SJjmy7
yn/uu2HwqpgUG9BpiG4yFjGXmefvUP0o/LGa+TzIIojlpWl7dGBzNJ12bi+0Dpq7
Ztv/xJFxA+2RBkRVHSMIyVopdtWNWl09adZjDWZY2muMEWEf0kogOKD8tvJ5Eru5
aMGH2/H4Fq26AKDpeS9BjQ61VmRFWr66WqCNVaq/4QKBgQDVY89lEB4Q10AUcKRB
v9dFX9KIcBfNqcKHELq5tthUFYqj/IyWIZ5GvAtgIO3yZ92EYW7g1WRz1rF37XIn
GafIk8m34Wq9+RJNc+hoPDRB/RTq5c97blUOl6FBhG/o35Wsr4N7jT844amSGZ/A
ct07yxgQWTIF4qQayFRnvUNyAwKBgQDJScqttoSeiu8E/7gIWODj5ZBF/vq8m74n
nKr6e2RZ6okhT0l52wK4rh91rGHdZoEJTE+0IZh4VlcjOarbpx//YcJCAHzDSlBM
yJ93Xu8zrTH64gitZfrzoPPvhFaPgQrShwHawhwm//BCFQ5MnpLZ2uMxUh+kQmfm
x4xj+K7i8QKBgQDO02P0P6/0gL1SUm9Sbv/W9O5ZYdQgedbbFML3OBrrPMnY8fLN
nR4MzzxzWtdmqXdSVSGj+BDaGhB+/f0zmrE+Psg4Wtsb8KrluV9ckGXSQ9ufZUk6
CJGWiC87EoNpgjRPYPqeqSPLHSY/PmjRnkOCLfJP/jP28lo+v0bYGeCiQwKBgGFm
M4ybJNESqVXh50sitq+QBZ/ZIbriIcFJLfLGgmh/9JsJoqQ0NbznhJGMOE7Jqua0
5lxjZUPVg5Sn8uUWmYUZ6MXHNpfI/dIpwgAhD94RkH21oj1Fe4kn+OGNR9Vou7Pj
YCJaiwTUE43mYmTw1l5UbFsRQf5Zo60oIea+DuIBAoGBAJuiSHfXlv9OdlLghiFk
XJs4spEqeAS+nfx2BScT2ft4MC5x0cUPovQ6AL/6YBCk+LDKqYn4UM4Aez5rnPPV
FqQXXmeGQndRvBrLb1tnviTi+uU8pGI/H5hiAC3B8nJKq8VlmBH34fKIuBR2Iuil
P85Yr82Fr8w1deA5U9Ear+gf
-----END PRIVATE KEY-----
47 changes: 47 additions & 0 deletions conf/tcpsplice.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
server
{
// log = "console()"
}

monitor
{
listen = "*:8000"
# acl
# {
# allow = [ "127.0.0.1" ]
# auth = [ "tcpsplice:monitor" ]
# }
}

services
{
rtmp
{
local = [ "*:1935" ]
remote = [ "my.server.com:1935" ]
// connect_timeout = 10
// write_timeout = 10
// idle_timeout = 60
// incoming_buffer_size = 64k
// outgoing_buffer_size = 64k
// log_minimum_size = 1k
// session_minimum_size = 1k
// meta_size = 16k
// meta_scan = "["
}

rtmps
{
local = [ "*:1936,conf/cert.pem,conf/key.pem" ]
remote = [ "my.server.com:1935" ]
// connect_timeout = 10
// write_timeout = 10
// idle_timeout = 60
// incoming_buffer_size = 64k
// outgoing_buffer_size = 64k
// log_minimum_size = 1k
// session_minimum_size = 1k
// meta_size = 16k
// meta_scan = "["
}
}
6 changes: 6 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
tcpsplice (1.2.0) stable; urgency=medium

* add native TLS support and modernize software packaging

-- Pierre-Yves Kerembellec <[email protected]> Thu, 11 Feb 2021 16:45:09 +0100

tcpsplice (1.1.0) stable; urgency=medium

* update to Go 1.15 (and Go modules)
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module tcpsplice
module main

go 1.15

require github.com/pyke369/golang-support v0.0.0-20200321184731-cd1ed731523d
require github.com/pyke369/golang-support v0.0.0-20210211171524-9d13f1802e2b
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
github.com/pyke369/golang-support v0.0.0-20200321184731-cd1ed731523d h1:bssjYWDUaYbjtBc7gZ6BI3YBerIg5EAn+kAM5hMQf2s=
github.com/pyke369/golang-support v0.0.0-20200321184731-cd1ed731523d/go.mod h1:0XGrzgrEp0fa/+JSV8XZePUwyjnU6C3bMc7Xz2bHHKI=
github.com/pyke369/golang-support v0.0.0-20210211171524-9d13f1802e2b h1:XamoXfiYhBSPMo9+rf5BIG0fmFzpoSyLUqsXTnnhydk=
github.com/pyke369/golang-support v0.0.0-20210211171524-9d13f1802e2b/go.mod h1:0XGrzgrEp0fa/+JSV8XZePUwyjnU6C3bMc7Xz2bHHKI=
70 changes: 40 additions & 30 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ package main

import (
"crypto/md5"
"crypto/tls"
"encoding/json"
"fmt"
"github.com/pyke369/golang-support/uconfig"
"github.com/pyke369/golang-support/ulog"
"math"
"math/rand"
"net"
Expand All @@ -16,10 +15,14 @@ import (
"strings"
"sync"
"time"

"github.com/pyke369/golang-support/dynacert"
"github.com/pyke369/golang-support/uconfig"
"github.com/pyke369/golang-support/ulog"
)

const progname = "tcpsplice"
const version = "1.1.0"
const version = "1.2.0"

type Session struct {
id, service, source, target, meta string
Expand All @@ -40,9 +43,9 @@ var (
sessionsLock sync.RWMutex
)

func serviceHandler(service string, listener *net.TCPListener) {
func serviceHandler(service string, listener net.Listener) {
for {
if source, err := listener.AcceptTCP(); err == nil {
if source, err := listener.Accept(); err == nil {
remotes := config.GetPaths(fmt.Sprintf("services.%s.remote", service))
if len(remotes) > 0 {
go func() {
Expand All @@ -57,8 +60,10 @@ func serviceHandler(service string, listener *net.TCPListener) {
idleTimeout := time.Second * time.Duration(config.GetDurationBounds(fmt.Sprintf("services.%s.idle_timeout", service), 60, 0, 300))
metaSize := int(config.GetSizeBounds(fmt.Sprintf("services.%s.meta_size", service), 16*1024, 0, 64*1024))
metaScan, _ := regexp.Compile(config.GetString(fmt.Sprintf("services.%s.meta_scan", service), "["))
source.SetReadBuffer(int(incomingSize))
source.SetWriteBuffer(int(incomingSize))
if tsource, ok := source.(*net.TCPConn); ok {
tsource.SetReadBuffer(int(incomingSize))
tsource.SetWriteBuffer(int(incomingSize))
}
target.(*net.TCPConn).SetReadBuffer(int(outgoingSize))
target.(*net.TCPConn).SetWriteBuffer(int(outgoingSize))
session := &Session{
Expand Down Expand Up @@ -208,23 +213,25 @@ func monitorHandler(response http.ResponseWriter, request *http.Request) {
services := map[string]interface{}{}
for _, service := range config.GetPaths("services") {
service = strings.TrimPrefix(service, "services.")
s := map[string]interface{}{}
entries := map[string]interface{}{}
sessionsLock.RLock()
for id, session := range sessions {
s[id] = map[string]interface{}{
"started": session.started.Unix(),
"duration": time.Now().Sub(session.started) / time.Second,
"source": session.source,
"target": session.target,
"bytes": [2]int64{session.sourceRead, session.targetRead},
"mean": [2]float64{session.sourceMeanThroughput, session.targetMeanThroughput},
"last": [2]float64{session.sourceLastThroughput, session.targetLastThroughput},
"meta": session.meta,
"done": session.done,
if session.service == service {
entries[id] = map[string]interface{}{
"started": session.started.Unix(),
"duration": time.Now().Sub(session.started) / time.Second,
"source": session.source,
"target": session.target,
"bytes": [2]int64{session.sourceRead, session.targetRead},
"mean": [2]float64{session.sourceMeanThroughput, session.targetMeanThroughput},
"last": [2]float64{session.sourceLastThroughput, session.targetLastThroughput},
"meta": session.meta,
"done": session.done,
}
}
}
sessionsLock.RUnlock()
services[service] = s
services[service] = entries
}
output["services"] = services
response.Header().Set("Content-Type", "application/json")
Expand All @@ -242,9 +249,6 @@ func monitorHandler(response http.ResponseWriter, request *http.Request) {
}
}
sessionsLock.RUnlock()
} else {
response.Header().Set("Content-Type", "text/html; charset=utf-8")
response.Write(monitorContent)
}
}

Expand Down Expand Up @@ -315,21 +319,27 @@ func main() {
for _, service := range config.GetPaths("services") {
for _, local := range config.GetPaths(fmt.Sprintf("%s.local", service)) {
service = strings.TrimPrefix(service, "services.")
local = config.GetString(local, "")
if address, err := net.ResolveTCPAddr("tcp", strings.TrimLeft(local, "*")); err == nil {
if listener, err := net.ListenTCP("tcp", address); err == nil {
logger.Info(map[string]interface{}{"type": "service", "name": service, "listen": local})
if parts := strings.Split(config.GetStringMatch(local, "_", "^.*?(:\\d+)?((,[^,]+){2})?$"), ","); parts[0] != "_" {
if listener, err := net.Listen("tcp", strings.TrimLeft(parts[0], "*")); err == nil {
if len(parts) > 1 {
loader := &dynacert.DYNACERT{Public: parts[1], Key: parts[2]}
listener = tls.NewListener(listener, dynacert.IntermediateTLSConfig(loader.GetCertificate))
logger.Info(map[string]interface{}{"type": "service", "name": service, "listen": parts[0], "cert": parts[1], "key": parts[2]})
} else {
logger.Info(map[string]interface{}{"type": "service", "name": service, "listen": parts[0]})
}
go serviceHandler(service, listener)
} else {
logger.Warn(map[string]interface{}{"type": "service", "name": service, "listen": local, "error": err})
logger.Warn(map[string]interface{}{"type": "service", "name": service, "listen": parts[0], "error": err})
}
} else {
logger.Warn(map[string]interface{}{"type": "service", "name": service, "listen": local, "error": err})
}
}
}

http.Handle("/", baseHandler(http.HandlerFunc(monitorHandler)))
http.Handle("/sessions.json", baseHandler(http.HandlerFunc(monitorHandler)))
http.Handle("/abort/", baseHandler(http.HandlerFunc(monitorHandler)))
http.Handle("/", baseHandler(http.StripPrefix("/", Resources(6*time.Hour))))

if parts := strings.Split(config.GetStringMatch("monitor.listen", "_", "^(?:\\*|\\d+(?:\\.\\d+){3}|\\[[^\\]]+\\])(?::\\d+)?(?:(?:,[^,]+){2})?$"), ","); parts[0] != "_" {
server := &http.Server{Addr: strings.TrimLeft(parts[0], "*")}
if len(parts) > 1 {
Expand Down
File renamed without changes.
32 changes: 0 additions & 32 deletions tcpsplice.conf

This file was deleted.

0 comments on commit cbc314f

Please sign in to comment.