Skip to content

Commit

Permalink
feat(CLI): command to list open conns
Browse files Browse the repository at this point in the history
  • Loading branch information
go-compile committed Jul 22, 2023
1 parent 87f2d5c commit 305183d
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 4 deletions.
1 change: 1 addition & 0 deletions cmd/localrelay/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ func help() {
fmt.Println(" localrelay start")
fmt.Println(" localrelay status")
fmt.Println(" localrelay monitor")
fmt.Println(" localrelay connections")
fmt.Println(" localrelay stop")
fmt.Println(" localrelay stop <relay>")
fmt.Println(" localrelay restart")
Expand Down
44 changes: 44 additions & 0 deletions cmd/localrelay/conns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

import (
"fmt"
"log"
"os"
"time"

"github.com/containerd/console"
)

func displayOpenConns() error {
// make terminal raw to allow the use of colour on windows terminals
current, _ := console.ConsoleFromFile(os.Stdout)
// NOTE: Docker healthchecks will panic "provided file is not a console"

if current != nil {
defer current.Reset()
}

if current != nil {
if err := current.SetRaw(); err != nil {
log.Println(err)
}
}

// we don't set terminal to raw here because print statements don't use
// carriage returns
conns, err := activeConnections()
if err != nil {

fmt.Printf("Daemon: \x1b[31m [OFFLINE] \x1b[0m\r\n")
fmt.Println(err)

// exit with error
os.Exit(1)
}

for _, conn := range conns {
fmt.Printf("%s -> %s (%s) (%s)\r\n", conn.RemoteAddr, conn.ForwardedAddr, conn.RelayName, formatDuration(time.Since(time.Unix(conn.Opened, 0))))
}

return nil
}
16 changes: 16 additions & 0 deletions cmd/localrelay/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,19 @@ type metrics struct {
In, Out, Active, DialAvg int
TotalConns, TotalRequests uint64
}

type connection struct {
ID int64

LocalAddr string
RemoteAddr string
Network string

RelayName string
RelayHost string

ForwardedAddr string

// Opened is a unix timestamp
Opened int64
}
31 changes: 31 additions & 0 deletions cmd/localrelay/ipc.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const (
daemonRun uint8 = iota
daemonStatus
daemonStop
daemonConns

maxErrors = 40
)
Expand Down Expand Up @@ -215,6 +216,36 @@ func ipcLoop(conn io.ReadWriteCloser) error {
lenbuf := make([]byte, 2)
binary.BigEndian.PutUint16(lenbuf, uint16(respBuf.Len()))

conn.Write(lenbuf)
conn.Write(respBuf.Bytes())
case daemonConns:
respBuf := bytes.NewBuffer(nil)

relayConns := make([]connection, 0, 200)

relays := runningRelaysCopy()
for _, r := range relays {
for _, conn := range r.GetConns() {

relayConns = append(relayConns, connection{
LocalAddr: conn.Conn.LocalAddr().String(),
RemoteAddr: conn.Conn.RemoteAddr().String(),
Network: conn.Conn.LocalAddr().Network(),

RelayName: r.Name,
RelayHost: r.Host,
ForwardedAddr: conn.RemoteAddr,

Opened: conn.Opened.Unix(),
})
}
}

json.NewEncoder(respBuf).Encode(relayConns)

lenbuf := make([]byte, 2)
binary.BigEndian.PutUint16(lenbuf, uint16(respBuf.Len()))

conn.Write(lenbuf)
conn.Write(respBuf.Bytes())
default:
Expand Down
26 changes: 26 additions & 0 deletions cmd/localrelay/ipcClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,29 @@ func stopRelay(relayName string) error {

return nil
}

func activeConnections() ([]connection, error) {
conn, err := IPCConnect()
if err != nil {
return nil, err
}

defer conn.Close()

_, err = conn.Write([]byte{0, 3, daemonConns, 0, 0})
if err != nil {
return nil, err
}

payload, err := readCommand(conn)
if err != nil {
return nil, err
}

var pool []connection
if err := json.Unmarshal(payload, &pool); err != nil {
return nil, err
}

return pool, nil
}
8 changes: 8 additions & 0 deletions cmd/localrelay/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"fmt"
"log"
"os"
"strings"
"time"

Expand Down Expand Up @@ -131,6 +132,13 @@ func main() {
}

fmt.Println("Daemon has been started")
return
case "conns", "connections":
if err := displayOpenConns(); err != nil {
fmt.Println(err)
os.Exit(1)
}

return
case "status":
if err := relayStatus(); err != nil {
Expand Down
36 changes: 33 additions & 3 deletions relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http"
"strings"
"sync"
"time"

"github.com/pkg/errors"
"golang.org/x/net/proxy"
Expand Down Expand Up @@ -61,7 +62,14 @@ type Relay struct {
protocolSwitching map[int]string

// connPool contains a list of ACTIVE connections
connPool []net.Conn
connPool []*PooledConn
}

// PooledConn allows meta data to be attached to a connection
type PooledConn struct {
Conn net.Conn
RemoteAddr string
Opened time.Time
}

const (
Expand Down Expand Up @@ -294,7 +302,7 @@ func (r *Relay) storeConn(conn net.Conn) {
r.m.Lock()
defer r.m.Unlock()

r.connPool = append(r.connPool, conn)
r.connPool = append(r.connPool, &PooledConn{conn, "", time.Now()})
}

// popConn removes the provided connection from the conn pool
Expand All @@ -303,10 +311,32 @@ func (r *Relay) popConn(conn net.Conn) {
defer r.m.Unlock()

for i := 0; i < len(r.connPool); i++ {
if r.connPool[i] == conn {
if r.connPool[i].Conn == conn {
// remove conn
r.connPool = append(r.connPool[:i], r.connPool[i+1:]...)
return
}
}
}

// setConnRemote will update the conn pool with the remote
func (r *Relay) setConnRemote(conn net.Conn, remote net.Addr) {
r.m.Lock()
defer r.m.Unlock()

for i := 0; i < len(r.connPool); i++ {
if r.connPool[i].Conn == conn {
// remove conn
r.connPool[i].RemoteAddr = remote.String()
return
}
}
}

// GetConns returns all the active connections to this relay
func (r *Relay) GetConns() []*PooledConn {
r.m.Lock()
defer r.m.Unlock()

return r.connPool
}
2 changes: 1 addition & 1 deletion relay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func TestConnPool(t *testing.T) {
relay.popConn(conn)

for _, c := range relay.connPool {
if c == conn {
if c.Conn == conn {
t.Fatal("correct conn was not removed")
}
}
Expand Down
3 changes: 3 additions & 0 deletions relaytcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ func handleConn(r *Relay, conn net.Conn, network string) {
r.Metrics.dial(1, 0, start)

r.logger.Info.Printf("CONNECTED TO %s\n", r.ForwardAddr)
r.setConnRemote(conn, c.RemoteAddr())

err = streamConns(conn, c, r.Metrics)
if err != nil {
Expand Down Expand Up @@ -120,6 +121,8 @@ func handleConn(r *Relay, conn net.Conn, network string) {
r.Metrics.dial(1, 0, start)

r.logger.Info.Printf("CONNECTED TO %s\n", r.ForwardAddr)
r.setConnRemote(conn, c.RemoteAddr())

err = streamConns(conn, c, r.Metrics)
if err != nil {
r.logger.Info.Printf("ERROR FROM %q ON %q: ERR=%s\n", conn.RemoteAddr(), conn.LocalAddr(), err)
Expand Down

0 comments on commit 305183d

Please sign in to comment.