lots of restructuring.

Experimensts with websockets over yamux failed. Now going to use a
second connection to the server from the agent.
This commit is contained in:
Erik Brakkee 2024-07-20 21:55:34 +02:00
parent 98e46ff7cc
commit 8981efd0b5
9 changed files with 142 additions and 56 deletions

View File

@ -3,6 +3,7 @@ package main
import ( import (
"bufio" "bufio"
"cidebug/pkg/iowrappers" "cidebug/pkg/iowrappers"
"cidebug/pkg/websocketutil"
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
"crypto/x509" "crypto/x509"
@ -98,6 +99,7 @@ func sshServer(hostKeyFile string) *ssh.Server {
} }
func echoServer(conn io.ReadWriter) { func echoServer(conn io.ReadWriter) {
log.Println("Echo service started")
io.Copy(conn, conn) io.Copy(conn, conn)
} }
@ -168,7 +170,7 @@ func main() {
log.Println("WebSocket connection error:", err) log.Println("WebSocket connection error:", err)
return return
} }
wsConn := iowrappers.NewWebSocketConn(conn) wsConn := websocketutil.NewWebSocketConn(conn)
defer wsConn.Close() defer wsConn.Close()
listener, err := yamux.Server(wsConn, nil) listener, err := yamux.Server(wsConn, nil)
@ -176,14 +178,12 @@ func main() {
panic(err) panic(err)
} }
log.Println("Connection established to rendez-vous server, waiting for debug sessions") // Need to create listener implementation that aactually listens for websocket connections.
var service AgentService var service AgentService
service = ListenerServer(func() *ssh.Server { service = ListenerServer(func() *ssh.Server {
return sshServer("hostkey.pem") return sshServer("hostkey.pem")
}) })
//service = ConnectionServer(netCatServer)
//service = ConnectionServer(echoServer) //service = ConnectionServer(echoServer)
//service := ConnectionServer(netCatServer)
service.Run(listener) service.Run(listener)
} }

View File

@ -2,10 +2,10 @@ package main
import ( import (
"cidebug/pkg/converge" "cidebug/pkg/converge"
"cidebug/pkg/iowrappers"
"cidebug/pkg/websocketutil" "cidebug/pkg/websocketutil"
"fmt" "fmt"
"log" "log"
"net"
"net/http" "net/http"
"regexp" "regexp"
) )
@ -23,7 +23,7 @@ func main() {
admin := converge.NewAdmin() admin := converge.NewAdmin()
registrationService := websocketutil.WebSocketService{ registrationService := websocketutil.WebSocketService{
Handler: func(w http.ResponseWriter, r *http.Request, conn iowrappers.ReadWriteAddrCloser) { Handler: func(w http.ResponseWriter, r *http.Request, conn net.Conn) {
publicId, err := parsePublicId(r.URL.Path) publicId, err := parsePublicId(r.URL.Path)
if err != nil { if err != nil {
log.Printf("Cannot parse public id from url: '%v'\n", err) log.Printf("Cannot parse public id from url: '%v'\n", err)
@ -37,7 +37,7 @@ func main() {
}, },
} }
clientService := websocketutil.WebSocketService{ clientService := websocketutil.WebSocketService{
Handler: func(w http.ResponseWriter, r *http.Request, conn iowrappers.ReadWriteAddrCloser) { Handler: func(w http.ResponseWriter, r *http.Request, conn net.Conn) {
publicId, err := parsePublicId(r.URL.Path) publicId, err := parsePublicId(r.URL.Path)
if err != nil { if err != nil {
log.Printf("Cannot parse public id from url: '%v'\n", err) log.Printf("Cannot parse public id from url: '%v'\n", err)

View File

@ -2,6 +2,7 @@ package main
import ( import (
"cidebug/pkg/iowrappers" "cidebug/pkg/iowrappers"
"cidebug/pkg/websocketutil"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"log" "log"
"net" "net"
@ -24,7 +25,7 @@ func handleConnection(conn net.Conn, wsURL string) {
log.Println("WebSocket connection error:", err) log.Println("WebSocket connection error:", err)
return return
} }
wsConn := iowrappers.NewWebSocketConn(_wsConn) wsConn := websocketutil.NewWebSocketConn(_wsConn)
defer wsConn.Close() defer wsConn.Close()
iowrappers.SynchronizeStreams(wsConn, conn) iowrappers.SynchronizeStreams(wsConn, conn)

View File

@ -2,6 +2,7 @@ package main
import ( import (
"cidebug/pkg/iowrappers" "cidebug/pkg/iowrappers"
"cidebug/pkg/websocketutil"
"fmt" "fmt"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"log" "log"
@ -34,7 +35,7 @@ func main() {
func handleWebSocket(w http.ResponseWriter, r *http.Request, tcpConn net.Conn) { func handleWebSocket(w http.ResponseWriter, r *http.Request, tcpConn net.Conn) {
conn, err := upgrader.Upgrade(w, r, nil) conn, err := upgrader.Upgrade(w, r, nil)
wsConn := iowrappers.NewWebSocketConn(conn) wsConn := websocketutil.NewWebSocketConn(conn)
if err != nil { if err != nil {
log.Println("Error upgrading to WebSocket:", err) log.Println("Error upgrading to WebSocket:", err)
return return

View File

@ -34,7 +34,8 @@ func NewAgent(publicId string,
} }
} }
func NewClient(publicId string, clientConn iowrappers.ReadWriteAddrCloser, agentConn net.Conn) *Client { func NewClient(publicId string, clientConn iowrappers.ReadWriteAddrCloser,
agentConn net.Conn) *Client {
return &Client{ return &Client{
publicId: publicId, publicId: publicId,
agent: agentConn, agent: agentConn,
@ -105,10 +106,13 @@ func (admin *Admin) addClient(publicId string, clientConn iowrappers.ReadWriteAd
// we should setup on-demend connections ot agents later. // we should setup on-demend connections ot agents later.
return nil, fmt.Errorf("No agent found for publicId '%s'", publicId) return nil, fmt.Errorf("No agent found for publicId '%s'", publicId)
} }
agentConn, err := agent.clientSession.Open() agentConn, err := agent.clientSession.Open()
if err != nil { if err != nil {
return nil, err return nil, err
} }
log.Println("Successful websocket connection to agent")
client := NewClient(publicId, clientConn, agentConn) client := NewClient(publicId, clientConn, agentConn)
admin.clients = append(admin.clients, client) admin.clients = append(admin.clients, client)
admin.logStatus() admin.logStatus()
@ -180,6 +184,7 @@ func (admin *Admin) Connect(publicId string, conn iowrappers.ReadWriteAddrCloser
admin.RemoveClient(client) admin.RemoveClient(client)
}() }()
log.Printf("Connecting client and agent: '%s'\n", publicId) log.Printf("Connecting client and agent: '%s'\n", publicId)
iowrappers.SynchronizeStreams(client.client, client.agent) iowrappers.SynchronizeStreams(client.client, client.agent)
return nil return nil
} }

View File

@ -1,53 +1,12 @@
package iowrappers package iowrappers
import ( import (
"github.com/gorilla/websocket"
"io" "io"
"net" "net"
) )
type WebSocketConn struct {
conn *websocket.Conn
buf []byte
}
type ReadWriteAddrCloser interface { type ReadWriteAddrCloser interface {
io.ReadWriteCloser io.ReadWriteCloser
RemoteAddr() net.Addr RemoteAddr() net.Addr
} }
func (websocketConn *WebSocketConn) Read(p []byte) (n int, err error) {
if len(websocketConn.buf) == 0 {
_, message, err := websocketConn.conn.ReadMessage()
if err != nil {
return 0, err
}
websocketConn.buf = message
}
n = copy(p, websocketConn.buf)
websocketConn.buf = websocketConn.buf[n:]
return n, err
}
func NewWebSocketConn(conn *websocket.Conn) *WebSocketConn {
return &WebSocketConn{conn: conn}
}
func (websocketConn *WebSocketConn) Write(p []byte) (n int, err error) {
err = websocketConn.conn.WriteMessage(websocket.BinaryMessage, p)
if err == nil {
n = len(p)
}
return n, err
}
func (websocketConn *WebSocketConn) Close() error {
return websocketConn.conn.Close()
}
func (websocketConn *WebSocketConn) RemoteAddr() net.Addr {
return websocketConn.conn.RemoteAddr()
}

View File

@ -0,0 +1,77 @@
package websocketutil
import (
"github.com/gorilla/websocket"
"net"
"time"
)
type WebSocketConn struct {
conn *websocket.Conn
buf []byte
}
func (websocketConn *WebSocketConn) Read(p []byte) (n int, err error) {
if len(websocketConn.buf) == 0 {
_, message, err := websocketConn.conn.ReadMessage()
if err != nil {
return 0, err
}
websocketConn.buf = message
}
n = copy(p, websocketConn.buf)
websocketConn.buf = websocketConn.buf[n:]
return n, err
}
func NewWebSocketConn(conn *websocket.Conn) *WebSocketConn {
return &WebSocketConn{conn: conn}
}
func (websocketConn *WebSocketConn) Write(p []byte) (n int, err error) {
err = websocketConn.conn.WriteMessage(websocket.BinaryMessage, p)
if err == nil {
n = len(p)
}
return n, err
}
func (websocketConn *WebSocketConn) Close() error {
return websocketConn.conn.Close()
}
func (WebSocketConn *WebSocketConn) LocalAddr() net.Addr {
return WebSocketConn.conn.LocalAddr()
}
func (websocketConn *WebSocketConn) RemoteAddr() net.Addr {
return websocketConn.conn.RemoteAddr()
}
func (websocketConn *WebSocketConn) SetDeadline(t time.Time) error {
return nil
}
func (websocketConn *WebSocketConn) SetReadDeadline(t time.Time) error {
return nil
}
func (websocketConn *WebSocketConn) SetWriteDeadline(t time.Time) error {
return nil
}
func ConnectWebSocket(conn net.Conn, urlStr string) (net.Conn, error) {
dialer := *websocket.DefaultDialer
dialer.NetDial = func(network, addr string) (net.Conn, error) {
return conn, nil
}
wsConn, _, err := dialer.Dial(urlStr, nil)
if err != nil {
return nil, err
}
return NewWebSocketConn(wsConn), nil
}

View File

@ -0,0 +1,34 @@
package websocketutil
import (
"log"
"net"
)
type WebSocketListener struct {
connections chan net.Conn
}
func NewWebSocketListener() WebSocketListener {
return WebSocketListener{
connections: make(chan net.Conn),
}
}
func (listener WebSocketListener) Accept() (net.Conn, error) {
conn := <-listener.connections
log.Printf("Got client connection: %v\n", conn)
return conn, nil
}
func (listener *WebSocketListener) NewConnection(conn net.Conn) {
listener.connections <- conn
}
func (listener WebSocketListener) Close() error {
return nil
}
func (listener WebSocketListener) Addr() net.Addr {
return WebSocketAddr("rendez-vous")
}

View File

@ -1,32 +1,41 @@
package websocketutil package websocketutil
import ( import (
"cidebug/pkg/iowrappers"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"log" "log"
"net"
"net/http" "net/http"
) )
type WebSocketAddr string
func (r WebSocketAddr) Network() string {
return "websocket"
}
func (r WebSocketAddr) String() string {
return string(r)
}
var upgrader = websocket.Upgrader{ var upgrader = websocket.Upgrader{
ReadBufferSize: 1024, ReadBufferSize: 1024,
WriteBufferSize: 1024, WriteBufferSize: 1024,
} }
func handleWebSocket(w http.ResponseWriter, r *http.Request, func handleWebSocket(w http.ResponseWriter, r *http.Request,
handler func(w http.ResponseWriter, r *http.Request, websockerConnection iowrappers.ReadWriteAddrCloser)) { handler func(w http.ResponseWriter, r *http.Request, websockerConnection net.Conn)) {
conn, err := upgrader.Upgrade(w, r, nil) conn, err := upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
log.Println("Error upgrading to WebSocket:", err) log.Println("Error upgrading to WebSocket:", err)
return return
} }
wsConn := iowrappers.NewWebSocketConn(conn) wsConn := NewWebSocketConn(conn)
defer wsConn.Close() defer wsConn.Close()
handler(w, r, wsConn) handler(w, r, wsConn)
} }
type WebSocketService struct { type WebSocketService struct {
Handler func(w http.ResponseWriter, r *http.Request, conn iowrappers.ReadWriteAddrCloser) Handler func(w http.ResponseWriter, r *http.Request, conn net.Conn)
} }
func (endpoint *WebSocketService) Handle(w http.ResponseWriter, r *http.Request) { func (endpoint *WebSocketService) Handle(w http.ResponseWriter, r *http.Request) {