Skip to content

Commit

Permalink
refactor: switch to shorter request id (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
knight42 authored Aug 20, 2023
1 parent 3d8f08c commit 914fd83
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 50 deletions.
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist/
.git/
4 changes: 1 addition & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
IMAGE_TAG ?= latest

NAME := kubectl-relay
VERSION ?= $(shell git describe --tags || echo "unknown")
GO_LDFLAGS = "-w -s -X github.com/knight42/krelay/pkg/constants.ClientVersion=$(VERSION)"
GOBUILD = CGO_ENABLED=0 go build -trimpath -ldflags $(GO_LDFLAGS)
GOBUILD = CGO_ENABLED=0 go build -trimpath

.PHONY: server-image push-server-image
server-image:
Expand Down
File renamed without changes.
9 changes: 4 additions & 5 deletions cmd/client/tcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"io"
"net"

"github.com/google/uuid"
"k8s.io/apimachinery/pkg/util/httpstream"
"k8s.io/klog/v2"

Expand All @@ -16,17 +15,17 @@ import (
func handleTCPConn(clientConn net.Conn, serverConn httpstream.Connection, dstAddr xnet.Addr, dstPort uint16) {
defer clientConn.Close()

requestID := uuid.New()
kvs := []any{constants.LogFieldRequestID, requestID.String()}
requestID := xnet.NewRequestID()
kvs := []any{constants.LogFieldRequestID, requestID}
defer klog.V(4).InfoS("handleTCPConn exit", kvs...)
klog.InfoS("Handling tcp connection",
constants.LogFieldRequestID, requestID.String(),
constants.LogFieldRequestID, requestID,
constants.LogFieldDestAddr, xnet.JoinHostPort(dstAddr.String(), dstPort),
constants.LogFieldLocalAddr, clientConn.LocalAddr().String(),
"clientAddr", clientConn.RemoteAddr().String(),
)

dataStream, errorChan, err := createStream(serverConn, requestID.String())
dataStream, errorChan, err := createStream(serverConn, requestID)
if err != nil {
klog.ErrorS(err, "Fail to create stream", kvs...)
return
Expand Down
9 changes: 4 additions & 5 deletions cmd/client/udp.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"net"

"github.com/google/uuid"
"k8s.io/apimachinery/pkg/util/httpstream"
"k8s.io/klog/v2"

Expand All @@ -13,20 +12,20 @@ import (
)

func handleUDPConn(clientConn net.PacketConn, cliAddr net.Addr, dataCh chan []byte, finish chan<- string, serverConn httpstream.Connection, dstAddr xnet.Addr, dstPort uint16) {
requestID := uuid.New()
kvs := []any{constants.LogFieldDestAddr, requestID.String()}
requestID := xnet.NewRequestID()
kvs := []any{constants.LogFieldDestAddr, requestID}
defer klog.V(4).InfoS("handleUDPConn exit", kvs...)
defer func() {
finish <- cliAddr.String()
}()
klog.InfoS("Handling udp connection",
constants.LogFieldRequestID, requestID.String(),
constants.LogFieldRequestID, requestID,
constants.LogFieldDestAddr, xnet.JoinHostPort(dstAddr.String(), dstPort),
constants.LogFieldLocalAddr, clientConn.LocalAddr().String(),
"clientAddr", cliAddr.String(),
)

dataStream, errorChan, err := createStream(serverConn, requestID.String())
dataStream, errorChan, err := createStream(serverConn, requestID)
if err != nil {
klog.ErrorS(err, "Fail to create stream", kvs...)
return
Expand Down
1 change: 1 addition & 0 deletions cmd/client/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func ensureServerPod(ctx context.Context, cs kubernetes.Interface, svrImg, names
GenerateName: constants.ServerName + "-",
Labels: map[string]string{
"app.kubernetes.io/name": constants.ServerName,
"app": constants.ServerName,
},
},
Spec: corev1.PodSpec{
Expand Down
14 changes: 7 additions & 7 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,24 +56,24 @@ func handleConn(ctx context.Context, c *net.TCPConn, dialer *net.Dialer) {
case xnet.ProtocolTCP:
upstreamConn, err := dialer.DialContext(ctx, constants.ProtocolTCP, dstAddr)
if err != nil {
klog.ErrorS(err, "Fail to create tcp connection", constants.LogFieldRequestID, hdr.RequestID.String(), constants.LogFieldDestAddr, dstAddr)
klog.ErrorS(err, "Fail to create tcp connection", constants.LogFieldRequestID, hdr.RequestID, constants.LogFieldDestAddr, dstAddr)
return
}
klog.InfoS("Start proxy tcp request", constants.LogFieldRequestID, hdr.RequestID.String(), constants.LogFieldDestAddr, dstAddr)
xnet.ProxyTCP(hdr.RequestID.String(), c, upstreamConn.(*net.TCPConn))
klog.InfoS("Start proxy tcp request", constants.LogFieldRequestID, hdr.RequestID, constants.LogFieldDestAddr, dstAddr)
xnet.ProxyTCP(hdr.RequestID, c, upstreamConn.(*net.TCPConn))

case xnet.ProtocolUDP:
upstreamConn, err := dialer.DialContext(ctx, constants.ProtocolUDP, dstAddr)
if err != nil {
klog.ErrorS(err, "Fail to create udp connection", constants.LogFieldRequestID, hdr.RequestID.String(), constants.LogFieldDestAddr, dstAddr)
klog.ErrorS(err, "Fail to create udp connection", constants.LogFieldRequestID, hdr.RequestID, constants.LogFieldDestAddr, dstAddr)
return
}
klog.InfoS("Start proxy udp request", constants.LogFieldRequestID, hdr.RequestID.String(), constants.LogFieldDestAddr, dstAddr)
klog.InfoS("Start proxy udp request", constants.LogFieldRequestID, hdr.RequestID, constants.LogFieldDestAddr, dstAddr)
udpConn := &xnet.UDPConn{UDPConn: upstreamConn.(*net.UDPConn)}
xnet.ProxyUDP(hdr.RequestID.String(), c, udpConn)
xnet.ProxyUDP(hdr.RequestID, c, udpConn)

default:
klog.InfoS("Unknown protocol", constants.LogFieldRequestID, hdr.RequestID.String(), constants.LogFieldDestAddr, dstAddr, constants.LogFieldProtocol, hdr.Protocol)
klog.InfoS("Unknown protocol", constants.LogFieldRequestID, hdr.RequestID, constants.LogFieldDestAddr, dstAddr, constants.LogFieldProtocol, hdr.Protocol)
}
}

Expand Down
3 changes: 1 addition & 2 deletions cmd/server/tcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"testing"
"time"

"github.com/google/uuid"
"github.com/stretchr/testify/require"

"github.com/knight42/krelay/pkg/testutils/tcp"
Expand Down Expand Up @@ -41,7 +40,7 @@ func TestHandleTCPConn(t *testing.T) {
return nil, fmt.Errorf("dial: %w", err)
}
hdr := xnet.Header{
RequestID: uuid.New(),
RequestID: xnet.NewRequestID(),
Protocol: xnet.ProtocolTCP,
Port: tsPort,
Addr: xnet.AddrFromHost(tsURL.Hostname()),
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module github.com/knight42/krelay
go 1.21

require (
github.com/google/uuid v1.3.0
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.4
k8s.io/api v0.28.0
Expand All @@ -29,6 +28,7 @@ require (
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
Expand Down
67 changes: 50 additions & 17 deletions pkg/xnet/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,57 @@ import (
"encoding/binary"
"fmt"
"io"
"math/rand"
)

"github.com/google/uuid"
const (
lengthAllMandatoryFields = 12 // 1(version) + 2(total length) + 5(request id) + 1(protocol) + 2(port) + 1(addr type)
lengthRequestID = 5
)

const totalLenOfOtherFields = 23 // 1(version) + 2(total length) + 16(uuid) + 1(protocol) + 2(port) + 1(addr type)
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")

func NewRequestID() string {
b := make([]rune, lengthRequestID)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}

type Header struct {
Version byte
RequestID uuid.UUID
RequestID string
Protocol byte
Port uint16
Addr Addr
}

func (h *Header) Marshal() []byte {
addrBytes := h.Addr.Marshal()
totalLen := totalLenOfOtherFields + len(addrBytes)
totalLen := lengthAllMandatoryFields + len(addrBytes)
buf := make([]byte, totalLen)
buf[0] = h.Version
binary.BigEndian.PutUint16(buf[1:3], uint16(totalLen))
copy(buf[3:19], h.RequestID[:])
buf[19] = h.Protocol
binary.BigEndian.PutUint16(buf[20:22], h.Port)
buf[22] = h.Addr.typ
copy(buf[23:], addrBytes)

cursor := 0
buf[cursor] = h.Version
cursor++

binary.BigEndian.PutUint16(buf[cursor:cursor+2], uint16(totalLen))
cursor += 2

copy(buf[cursor:cursor+lengthRequestID], h.RequestID)
cursor += lengthRequestID

buf[cursor] = h.Protocol
cursor++

binary.BigEndian.PutUint16(buf[cursor:cursor+2], h.Port)
cursor += 2

buf[cursor] = h.Addr.typ
cursor++

copy(buf[cursor:], addrBytes)
return buf
}

Expand All @@ -41,7 +67,7 @@ func (h *Header) FromReader(r io.Reader) error {
h.Version = lengthBuf[0]
// TODO: handle different versions
totalLen := binary.BigEndian.Uint16(lengthBuf[1:])
if totalLen < totalLenOfOtherFields {
if totalLen < lengthAllMandatoryFields {
return fmt.Errorf("body too short: %d", totalLen)
}

Expand All @@ -51,12 +77,19 @@ func (h *Header) FromReader(r io.Reader) error {
return fmt.Errorf("read full body: %w", err)
}

reqIDBytes := bodyBuf[:16]
proto := bodyBuf[16]
port := binary.BigEndian.Uint16(bodyBuf[17:19])
h.RequestID, _ = uuid.FromBytes(reqIDBytes)
cursor := 0
reqIDBytes := bodyBuf[cursor : cursor+lengthRequestID]
cursor += lengthRequestID

proto := bodyBuf[cursor]
cursor++

port := binary.BigEndian.Uint16(bodyBuf[cursor : cursor+2])
cursor += 2

h.RequestID = string(reqIDBytes)
h.Protocol = proto
h.Port = port
h.Addr = AddrFromBytes(bodyBuf[19], bodyBuf[20:])
h.Addr = AddrFromBytes(bodyBuf[cursor], bodyBuf[cursor+1:])
return nil
}
21 changes: 11 additions & 10 deletions pkg/xnet/header_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,27 @@ import (
"net"
"testing"

"github.com/google/uuid"
"github.com/stretchr/testify/require"
)

var fakeRequestID = "00000"

var headerCases = map[string]struct {
hdr Header
bytes []byte
}{
"host": {
hdr: Header{
Version: 1,
RequestID: uuid.UUID{},
RequestID: fakeRequestID,
Protocol: ProtocolTCP,
Port: 80,
Addr: AddrFromHost("a.com"),
},
bytes: []byte{
1,
0, 0x1c,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0x11,
0x30, 0x30, 0x30, 0x30, 0x30,
0,
0, 80,
1,
Expand All @@ -34,15 +35,15 @@ var headerCases = map[string]struct {
"ipv4": {
hdr: Header{
Version: 0,
RequestID: uuid.UUID{},
RequestID: fakeRequestID,
Protocol: ProtocolUDP,
Port: 53,
Addr: AddrFromBytes(AddrTypeIP, net.IPv4(192, 168, 1, 1).To4()),
},
bytes: []byte{
0,
0, 0x1b,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0x10,
0x30, 0x30, 0x30, 0x30, 0x30,
1,
0, 53,
0,
Expand All @@ -52,15 +53,15 @@ var headerCases = map[string]struct {
"ipv6": {
hdr: Header{
Version: 0,
RequestID: uuid.UUID{},
RequestID: fakeRequestID,
Protocol: ProtocolTCP,
Port: 8080,
Addr: AddrFromBytes(AddrTypeIP, net.IPv6loopback),
},
bytes: []byte{
0,
0, 0x27,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0x1c,
0x30, 0x30, 0x30, 0x30, 0x30,
0,
0x1f, 0x90,
0,
Expand Down

0 comments on commit 914fd83

Please sign in to comment.