chore: Mostly ports SSHBackend.

This commit is contained in:
Tera << 8 2025-01-12 11:35:26 -05:00
parent 0d92d27427
commit 2c6b5eb5b9
Signed by: imterah
GPG key ID: 8FA7DD57BA6CEA37
5 changed files with 98 additions and 62 deletions

View file

@ -229,6 +229,7 @@ func (runtime *Runtime) goRoutineHandler() error {
}
}
case *commonbackend.ProxyStatusRequest:
command.Message()
err := handleCommand("proxyStatusRequest", command, sock, messageData.Channel)
if err != nil {

View file

@ -1,6 +1,9 @@
package backendutil
import "git.terah.dev/imterah/hermes/backend/commonbackend"
import (
"capnproto.org/go/capnp/v3"
"git.terah.dev/imterah/hermes/backend/commonbackend"
)
type BackendInterface interface {
StartBackend(arguments []byte) (bool, error)
@ -8,7 +11,15 @@ type BackendInterface interface {
GetBackendStatus() (bool, error)
StartProxy(command *commonbackend.AddProxy) (bool, error)
StopProxy(command *commonbackend.RemoveProxy) (bool, error)
GetAllClientConnections() []*commonbackend.ProxyClientConnection
CheckParametersForConnections(clientParameters *commonbackend.CheckClientParameters) *commonbackend.CheckParametersResponse
CheckParametersForBackend(arguments []byte) *commonbackend.CheckParametersResponse
GetAllClientConnections(seg *capnp.Segment) []*commonbackend.Connection
CheckParametersForConnections(clientParameters *commonbackend.CheckClientParameters) *CheckParametersResponse
CheckParametersForBackend(arguments []byte) *CheckParametersResponse
}
// Sent as a response to either CheckClientParameters or CheckBackendParameters
type CheckParametersResponse struct {
Type string // Will be 'checkParametersResponse' always
InResponseTo string // Will be either 'checkClientParameters' or 'checkServerParameters'
IsValid bool // If true, valid, and if false, invalid
Message string // String message from the client (ex. failed to unmarshal JSON: x is not defined)
}

View file

@ -31,23 +31,23 @@ func (backend *DummyBackend) StopProxy(command *commonbackend.RemoveProxy) (bool
return true, nil
}
func (backend *DummyBackend) GetAllClientConnections() []*commonbackend.ProxyClientConnection {
return []*commonbackend.ProxyClientConnection{}
func (backend *DummyBackend) GetAllClientConnections() []*commonbackend.Connection {
return []*commonbackend.Connection{}
}
func (backend *DummyBackend) CheckParametersForConnections(clientParameters *commonbackend.CheckClientParameters) *commonbackend.CheckParametersResponse {
func (backend *DummyBackend) CheckParametersForConnections(clientParameters *commonbackend.CheckClientParameters) *backendutil.CheckParametersResponse {
// You don't have to specify Type and InReplyTo. Those will be handled for you.
// Message is optional.
return &commonbackend.CheckParametersResponse{
return &backendutil.CheckParametersResponse{
IsValid: true,
Message: "Valid!",
}
}
func (backend *DummyBackend) CheckParametersForBackend(arguments []byte) *commonbackend.CheckParametersResponse {
func (backend *DummyBackend) CheckParametersForBackend(arguments []byte) *backendutil.CheckParametersResponse {
// You don't have to specify Type and InReplyTo. Those will be handled for you.
// Message is optional.
return &commonbackend.CheckParametersResponse{
return &backendutil.CheckParametersResponse{
IsValid: true,
Message: "Valid!",
}

View file

@ -21,11 +21,8 @@ type ProxyInstance struct {
Protocol string `json:"protocol"`
}
type WriteLogger struct {
UseError bool
}
type WriteLogger struct{}
// TODO: deprecate UseError switching
func (writer WriteLogger) Write(p []byte) (n int, err error) {
logSplit := strings.Split(string(p), "\n")
@ -34,11 +31,7 @@ func (writer WriteLogger) Write(p []byte) (n int, err error) {
continue
}
if writer.UseError {
log.Errorf("application: %s", line)
} else {
log.Infof("application: %s", line)
}
log.Infof("application: %s", line)
}
return len(p), err
@ -157,7 +150,7 @@ func entrypoint(cCtx *cli.Context) error {
if !command.IsRunning {
var status string
if command.StatusCode == commonbackend.StatusSuccess {
if command.StatusCode() == commonbackend.StatusCode_success {
status = "Success"
} else {
status = "Failure"
@ -236,19 +229,14 @@ func entrypoint(cCtx *cli.Context) error {
log.Debug("entering infinite keepalive loop...")
for {
time.Sleep(1 * time.Second)
}
}
}()
log.Debug("entering execution loop (in main goroutine)...")
stdout := WriteLogger{
UseError: false,
}
stderr := WriteLogger{
UseError: true,
}
logger := WriteLogger{}
for {
log.Info("starting process...")
@ -257,9 +245,7 @@ func entrypoint(cCtx *cli.Context) error {
cmd := exec.Command(executablePath)
cmd.Env = append(cmd.Env, fmt.Sprintf("HERMES_API_SOCK=%s", sockPath), fmt.Sprintf("HERMES_LOG_LEVEL=%s", logLevel))
cmd.Stdout = stdout
cmd.Stderr = stderr
cmd.Stdout, cmd.Stderr = logger, logger
err := cmd.Run()
if err != nil {

View file

@ -22,14 +22,14 @@ type SSHListener struct {
SourceIP string
SourcePort uint16
DestPort uint16
Protocol string // Will be either 'tcp' or 'udp'
Protocol commonbackend.Protocol
Listeners []net.Listener
}
type SSHBackend struct {
config *SSHBackendData
conn *ssh.Client
clients []*commonbackend.ProxyClientConnection
clients []*commonbackend.Connection
proxies []*SSHListener
arrayPropMutex sync.Mutex
}
@ -105,18 +105,31 @@ func (backend *SSHBackend) GetBackendStatus() (bool, error) {
}
func (backend *SSHBackend) StartProxy(command *commonbackend.AddProxy) (bool, error) {
sourceIPBytes, err := command.SourceIP()
if err != nil {
return false, err
}
// YOLO.
sourceIP, err := commonbackend.IPBytesToIPSafe(sourceIPBytes)
if err != nil {
return false, err
}
listenerObject := &SSHListener{
SourceIP: command.SourceIP,
SourcePort: command.SourcePort,
DestPort: command.DestPort,
Protocol: command.Protocol,
SourceIP: sourceIP.String(),
SourcePort: command.SourcePort(),
DestPort: command.DestPort(),
Protocol: command.Protocol(),
Listeners: []net.Listener{},
}
for _, ipListener := range backend.config.ListenOnIPs {
ip := net.TCPAddr{
IP: net.ParseIP(ipListener),
Port: int(command.DestPort),
Port: int(command.DestPort()),
}
listener, err := backend.conn.ListenTCP(&ip)
@ -158,7 +171,7 @@ func (backend *SSHBackend) StartProxy(command *commonbackend.AddProxy) (bool, er
}
clientIPAndPort := forwardedConn.RemoteAddr().String()
clientIP := clientIPAndPort[:strings.LastIndex(clientIPAndPort, ":")]
clientIPString := clientIPAndPort[:strings.LastIndex(clientIPAndPort, ":")]
clientPort, err := strconv.Atoi(clientIPAndPort[strings.LastIndex(clientIPAndPort, ":")+1:])
if err != nil {
@ -166,17 +179,21 @@ func (backend *SSHBackend) StartProxy(command *commonbackend.AddProxy) (bool, er
continue
}
advertisedConn := &commonbackend.ProxyClientConnection{
SourceIP: command.SourceIP,
SourcePort: command.SourcePort,
DestPort: command.DestPort,
ClientIP: clientIP,
ClientPort: uint16(clientPort),
clientIP, err := commonbackend.IPStringToIPBytes(clientIPString)
// FIXME (imterah): shouldn't protocol be in here?
// Protocol: command.Protocol,
if err != nil {
log.Warnf("failed to parse client IP: %s", err.Error())
continue
}
advertisedConn := &commonbackend.Connection{}
advertisedConn.SetSourceIP(sourceIPBytes)
advertisedConn.SetSourcePort(command.SourcePort())
advertisedConn.SetDestPort(command.DestPort())
advertisedConn.SetClientIP(clientIP)
advertisedConn.SetClientPort(uint16(clientPort))
backend.arrayPropMutex.Lock()
backend.clients = append(backend.clients, advertisedConn)
backend.arrayPropMutex.Unlock()
@ -278,7 +295,20 @@ func (backend *SSHBackend) StopProxy(command *commonbackend.RemoveProxy) (bool,
backend.arrayPropMutex.Lock()
for proxyIndex, proxy := range backend.proxies {
if command.SourceIP == proxy.SourceIP && command.SourcePort == proxy.SourcePort && command.DestPort == proxy.DestPort && command.Protocol == proxy.Protocol {
sourceIPBytes, err := command.SourceIP()
if err != nil {
log.Warnf("failed to get source IP: %s", err.Error())
continue
}
sourceIP, err := commonbackend.IPBytesToIPSafe(sourceIPBytes)
if err != nil {
log.Warnf("failed to get source IP: %s", err.Error())
}
if sourceIP.String() == proxy.SourceIP && command.SourcePort() == proxy.SourcePort && command.DestPort() == proxy.DestPort && command.Protocol() == proxy.Protocol {
for _, listener := range proxy.Listeners {
err := listener.Close()
@ -299,44 +329,44 @@ func (backend *SSHBackend) StopProxy(command *commonbackend.RemoveProxy) (bool,
return false, fmt.Errorf("could not find the proxy")
}
func (backend *SSHBackend) GetAllClientConnections() []*commonbackend.ProxyClientConnection {
func (backend *SSHBackend) GetAllClientConnections() []*commonbackend.Connection {
defer backend.arrayPropMutex.Unlock()
backend.arrayPropMutex.Lock()
return backend.clients
}
func (backend *SSHBackend) CheckParametersForConnections(clientParameters *commonbackend.CheckClientParameters) *commonbackend.CheckParametersResponse {
if clientParameters.Protocol != "tcp" {
return &commonbackend.CheckParametersResponse{
func (backend *SSHBackend) CheckParametersForConnections(clientParameters *commonbackend.CheckClientParameters) *backendutil.CheckParametersResponse {
if clientParameters.Protocol() != commonbackend.Protocol_tcp {
return &backendutil.CheckParametersResponse{
IsValid: false,
Message: "Only TCP is supported for SSH",
}
}
return &commonbackend.CheckParametersResponse{
return &backendutil.CheckParametersResponse{
IsValid: true,
}
}
func (backend *SSHBackend) CheckParametersForBackend(arguments []byte) *commonbackend.CheckParametersResponse {
func (backend *SSHBackend) CheckParametersForBackend(arguments []byte) *backendutil.CheckParametersResponse {
var backendData SSHBackendData
if err := json.Unmarshal(arguments, &backendData); err != nil {
return &commonbackend.CheckParametersResponse{
return &backendutil.CheckParametersResponse{
IsValid: false,
Message: fmt.Sprintf("could not read json: %s", err.Error()),
}
}
if err := validator.New().Struct(&backendData); err != nil {
return &commonbackend.CheckParametersResponse{
return &backendutil.CheckParametersResponse{
IsValid: false,
Message: fmt.Sprintf("failed validation of parameters: %s", err.Error()),
}
}
return &commonbackend.CheckParametersResponse{
return &backendutil.CheckParametersResponse{
IsValid: true,
}
}
@ -388,12 +418,20 @@ func (backend *SSHBackend) backendDisconnectHandler() {
log.Info("SSHBackend has reconnected successfully. Attempting to set up proxies again...")
for _, proxy := range backend.proxies {
ok, err := backend.StartProxy(&commonbackend.AddProxy{
SourceIP: proxy.SourceIP,
SourcePort: proxy.SourcePort,
DestPort: proxy.DestPort,
Protocol: proxy.Protocol,
})
sourceIP, err := commonbackend.IPStringToIPBytes(proxy.SourceIP)
if err != nil {
log.Warnf("Failed to parse IP address: %s", err.Error())
}
proxyStartCommand := &commonbackend.AddProxy{}
proxyStartCommand.SetSourceIP(sourceIP)
proxyStartCommand.SetSourcePort(proxy.SourcePort)
proxyStartCommand.SetDestPort(proxy.DestPort)
proxyStartCommand.SetProtocol(proxy.Protocol)
ok, err := backend.StartProxy(proxyStartCommand)
if err != nil {
log.Errorf("Failed to set up proxy: %s", err.Error())