164 lines
3.8 KiB
Go
Raw Normal View History

2024-11-13 22:45:03 +00:00
package term
2024-11-06 13:49:41 +00:00
import (
"crypto/tls"
"fmt"
"log"
"net/http"
"net/url"
"strconv"
"strings"
fastWs "github.com/fasthttp/websocket"
"github.com/gofiber/contrib/websocket"
2024-11-16 02:34:07 +07:00
"rul.sh/vaulterm/server/lib"
2024-11-06 13:49:41 +00:00
)
2024-11-06 17:32:39 +00:00
// https://github.com/proxmox/pve-xtermjs/blob/master/README
2024-11-07 19:07:41 +00:00
func NewTerminalSession(c *websocket.Conn, pve *lib.PVEServer, instance *lib.PVEInstance) error {
2024-11-06 17:32:39 +00:00
access, err := pve.GetAccessTicket()
if err != nil {
2024-11-07 19:07:41 +00:00
log.Println("Error getting access ticket:", err)
2024-11-06 17:32:39 +00:00
return err
}
ticket, err := pve.GetVNCTicket(access, instance, false)
if err != nil {
2024-11-07 19:07:41 +00:00
log.Println("Error getting vnc ticket:", err)
2024-11-06 17:32:39 +00:00
return err
}
2024-11-06 13:49:41 +00:00
url := fmt.Sprintf("wss://%s:%d/api2/json/nodes/%s/%s/%s/vncwebsocket?port=%s&vncticket=%s",
pve.HostName, pve.Port, instance.Node, instance.Type, instance.VMID, ticket.Port, url.QueryEscape(ticket.Ticket))
headers := http.Header{}
headers.Add("Authorization", "PVEAPIToken="+access.Username)
headers.Add("Cookie", "PVEAuthCookie="+access.Ticket)
dialer := fastWs.Dialer{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
ws, _, err := dialer.Dial(url, headers)
if err != nil {
log.Println("Error connecting to Proxmox WebSocket:", err)
return err
}
defer ws.Close()
// Send first ticket line
ws.WriteMessage(fastWs.TextMessage, []byte(fmt.Sprintf("%s:%s\n", access.Username, access.Ticket)))
go func() {
for {
t, msg, err := c.ReadMessage()
if err != nil {
log.Println("Error reading from client:", err)
break
}
if strings.HasPrefix(string(msg), "\x01") {
parts := strings.Split(string(msg[1:]), ",")
if len(parts) == 2 {
width, _ := strconv.Atoi(parts[0])
height, _ := strconv.Atoi(parts[1])
ws.WriteMessage(fastWs.TextMessage, []byte(fmt.Sprintf("1:%d:%d:", width, height)))
}
continue
}
msg = []byte(fmt.Sprintf("0:%d:%s\n", len(msg), string(msg)))
2024-11-06 17:32:39 +00:00
if err = ws.WriteMessage(t, msg); err != nil {
2024-11-06 13:49:41 +00:00
log.Println("Error writing to Proxmox:", err)
break
}
}
}()
for {
t, msg, err := ws.ReadMessage()
if err != nil {
log.Println("Error reading from Proxmox:", err)
break
}
if string(msg) == "OK" {
continue
}
2024-11-06 17:32:39 +00:00
if err = c.WriteMessage(t, msg); err != nil {
log.Println("Error writing to client:", err)
break
}
}
return nil
}
2024-11-07 19:07:41 +00:00
func NewVNCSession(c *websocket.Conn, pve *lib.PVEServer, instance *lib.PVEInstance) error {
2024-11-06 17:32:39 +00:00
access, err := pve.GetAccessTicket()
if err != nil {
2024-11-07 19:07:41 +00:00
log.Println("Error getting access ticket:", err)
2024-11-06 17:32:39 +00:00
return err
}
ticket, err := pve.GetVNCTicket(access, instance, true)
if err != nil {
2024-11-07 19:07:41 +00:00
log.Println("Error getting vnc ticket:", err)
2024-11-06 17:32:39 +00:00
return err
}
url := fmt.Sprintf("wss://%s:%d/api2/json/nodes/%s/%s/%s/vncwebsocket?port=%s&vncticket=%s",
pve.HostName, pve.Port, instance.Node, instance.Type, instance.VMID, ticket.Port, url.QueryEscape(ticket.Ticket))
headers := http.Header{}
headers.Add("Authorization", "PVEAPIToken="+access.Username)
headers.Add("Cookie", "PVEAuthCookie="+access.Ticket)
dialer := fastWs.Dialer{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
ws, _, err := dialer.Dial(url, headers)
if err != nil {
log.Println("Error connecting to Proxmox WebSocket:", err)
return err
}
defer ws.Close()
// Send vnc password
c.WriteMessage(fastWs.TextMessage, []byte(fmt.Sprintf("\x01%s", ticket.Ticket)))
go func() {
for {
t, msg, err := c.ReadMessage()
if err != nil {
log.Println("Error reading from client:", err)
break
}
if err = ws.WriteMessage(t, msg); err != nil {
log.Println("Error writing to Proxmox:", err)
break
}
}
}()
for {
t, msg, err := ws.ReadMessage()
2024-11-06 13:49:41 +00:00
if err != nil {
2024-11-06 17:32:39 +00:00
log.Println("Error reading from Proxmox:", err)
break
}
if err = c.WriteMessage(t, msg); err != nil {
2024-11-06 13:49:41 +00:00
log.Println("Error writing to client:", err)
break
}
}
return nil
}