opshandler.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package ops
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "github.com/gorilla/websocket"
  6. "udeServer/internal/svc"
  7. "udeServer/internal/types"
  8. "udeServer/internal/ws"
  9. )
  10. // upGrader 允许跨源升级;ws/ops 在审计中间件 skip 名单中,
  11. // 升级后按 WSRequest/WSResponse 消息驱动,不走 goctl 常规 logic 链。
  12. var upGrader = websocket.Upgrader{
  13. CheckOrigin: func(r *http.Request) bool { return true },
  14. }
  15. // OpsHandler 是 WebSocket 运维诊断入口(移植自 sdf-serve ops 模块):
  16. // 1. HTTP 升级成 WebSocket;2. 循环读 WSRequest;3. 校验目标后分发到 ws.Service。
  17. // 动作定义: ping(逐行回推)/traceroute(逐行回推)/telnet(连接成败+耗时)。
  18. func OpsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
  19. return func(w http.ResponseWriter, r *http.Request) {
  20. conn, err := upGrader.Upgrade(w, r, nil)
  21. if err != nil {
  22. return
  23. }
  24. defer conn.Close()
  25. for {
  26. _, message, err := conn.ReadMessage()
  27. if err != nil {
  28. break
  29. }
  30. var req types.WSRequest
  31. if err := json.Unmarshal(message, &req); err != nil {
  32. sendErr(conn, req.Action, "invalid request")
  33. continue
  34. }
  35. // 安全校验:防目标地址注入
  36. if req.Action == "ping" || req.Action == "traceroute" {
  37. if !ws.ValidateTarget(req.Target) {
  38. sendErr(conn, req.Action, "非法目标地址")
  39. continue
  40. }
  41. }
  42. if req.Action == "telnet" {
  43. if !ws.ValidateTarget(req.Host) || !ws.ValidatePort(req.Port) {
  44. sendErr(conn, "telnet", "非法 host 或 port")
  45. continue
  46. }
  47. }
  48. // 执行操作
  49. switch req.Action {
  50. case "ping":
  51. go svcCtx.WsServer.Ping(conn, req)
  52. case "traceroute":
  53. go svcCtx.WsServer.Traceroute(conn, req)
  54. case "telnet":
  55. go svcCtx.WsServer.Telnet(conn, req)
  56. default:
  57. sendErr(conn, req.Action, "unsupported action")
  58. }
  59. }
  60. }
  61. }
  62. func sendErr(conn *websocket.Conn, action, msg string) {
  63. _ = conn.WriteJSON(types.WSResponse{
  64. Action: action,
  65. Status: "error",
  66. Output: msg,
  67. })
  68. }