golang实现的交互shell

admin 2024年10月3日14:44:51评论12 views字数 2120阅读7分4秒阅读模式

最近在用golang写交互shell的代码,因为涉及到三端的问题浏览器、服务端、agent)需要一个websocket转发这部分。

golang实现的交互shell

问题就此开始

1、如何实现websocket转发,打通浏览器和agent的通讯?

这是基本架构,是不是挺简单的

浏览器->服务端->agent

agent->服务端->浏览器

2、如何把浏览器和agent对应起来,不让乱了套?

那就撸起袖子加油干,一段代码一包烟,一个破功能搞几天,我的基本思路:

浏览器有唯一标识websocket连接到服务端的handler1,把conn、唯一标识一起存到全局中(handler1只接收浏览器的连接)。

agent带有唯一标识websocket连接到服务端的handler2,通过判断唯一标识打通浏览器和agent。

这里就不贴出浏览器和agent的代码了。

使用到的项目一并分享(你看是不是很体贴):

linux交互shell:

https://github.com/creack/pty

windows交互shell(可能低版本windows不兼容):

https://github.com/ActiveState/termtest/conpty

前端xterm:

https://github.com/xtermjs/xterm.js

划重点:要想打通浏览器和agent的通讯,服务端作为中间人那么这时就需要下面服务端的相关操作了,不知道在哪个issues看到的忘记了,顺便记录一下,直接看服务端代码,非常优雅:

serverClosed := make(chan struct{})clientClosed := make(chan struct{})go copyConn(client.ws, ws, serverClosed, clientClosed)go copyConn(ws, client.ws, clientClosed, serverClosed)

func copyConn(readConn, writeConn *websocket.Conn, readClosed, writeClosed chan struct{}) {  var rerr error  for {    var r io.Reader    var messageType int    messageType, r, rerr = readConn.NextReader()    if rerr != nil {      break    }    w, err := writeConn.NextWriter(messageType)    if err != nil {      break    }    if _, err := io.Copy(w, r); err != nil {      break    }    if err := w.Close(); err != nil {      break    }  }  // Close the reading connection. If we broke out of the loop because of a  // normal close, then NextReader echoed the close message and we should now  // close the connection.  If it's an abnormal close, then we should give up  // and close the connection.  readConn.Close()  // Tell the other goroutine that readConn was closed.  close(readClosed)  // Did we break out of the loop because we received a close message?  if e, ok := rerr.(*websocket.CloseError); ok && e.Code != websocket.CloseAbnormalClosure {    // Forward the close message to writeConn.    var m []byte    if e.Code != websocket.CloseNoStatusReceived {      m = websocket.FormatCloseMessage(e.Code, e.Text)    }    err := writeConn.WriteMessage(websocket.CloseMessage, m)    // Did we successfully send the close message?    if err == nil {      // Wait with timeout for the other goroutine to handle the handshake.      select {      case <-writeClosed:        // The other goroutine closed writeConn.        return      case <-time.After(10 * time.Second):      }    }  }  // A blocked reader returns with an error when the connection is closed.  writeConn.Close()}

仅限交流学习使用,如您在使用本工具或代码的过程中存在任何非法行为,您需自行承担相应后果,我们将不承担任何法律及连带责任。“如侵权请私聊公众号删文”。

原文始发于微信公众号(柠檬赏金猎人):golang实现的交互shell

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月3日14:44:51
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   golang实现的交互shellhttps://cn-sec.com/archives/3229755.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息