chisel 分析2 代码逻辑
测试环境如下:
centosA:192.168.1.206 ./chisel client -v 192.168.1.207:12345 192.168.1.206:8888:socks
centosB:192.168.1.207 ./chisel server -v --host 192.168.1.207 -p 12345 --socks5
浏览器上设置socks代理到192.168.1.206 8888 , 在浏览器访问192.168.1.4 8001
浏览器结果如下:
来看client代码分析:
查看代码
./chisel client -v 192.168.1.207:12345 192.168.1.206:8888:socks
2024/01/07 01:35:45 client: tun: [tunnel.go:67] Created
2024/01/07 01:35:45 client: [client.go:249] Connecting to ws://192.168.1.207:12345
2024/01/07 01:35:45 client: tun: [tunnel.go:154] new proxy remote-> &settings.Remote{LocalHost:"192.168.1.206", LocalPort:"8888", LocalProto:"tcp", RemoteHost:"", RemotePort:"", RemoteProto:"tcp", Socks:true, Reverse:false, Stdio:false}
2024/01/07 01:35:45 client: tun: proxy#192.168.1.206:8888=>socks: [tunnel_in_proxy.go:58] Listening
2024/01/07 01:35:45 client: tun: [tunnel.go:170] Bound proxies
2024/01/07 01:35:45 client: [client_connect.go:93] c.server:ws://192.168.1.207:12345 head:map[]
2024/01/07 01:35:45 client: [client_connect.go:100] Handshaking...
client version:SSH-chisel-v3-client
versionline:[83 83 72 45 99 104 105 115 101 108 45 118 51 45 99 108 105 101 110 116] (SSH-chisel-v3-client)
resp versionline:[83 83 72 45 99 104 105 115 101 108 45 118 51 45 115 101 114 118 101 114] (SSH-chisel-v3-server)
serverVersion :SSH-chisel-v3-server dialAddress: remote:192.168.1.207:12345
2024/01/07 01:35:45 client: [client_connect.go:115] Sending config 0.0.0-src []string{"192.168.1.206:8888:socks"}
2024/01/07 01:35:45 client: [client_connect.go:129] Connected (Latency 1.526593ms)
2024/01/07 01:35:45 client: tun: [tunnel.go:96] SSH connected
2024/01/07 01:35:50 client: tun: proxy#192.168.1.206:8888=>socks: conn#1: [tunnel_in_proxy.go:135] Open------> socks
OpenChannel chisel
2024/01/07 01:35:50 client: tun: proxy#192.168.1.206:8888=>socks: conn#1: [tunnel_in_proxy.go:142] client send OpenChannel chisel
chan type:chisel extra:socks
chan type:chisel extra:socks wait PeersID [0] confim
2024/01/07 01:35:50 client: tun: proxy#192.168.1.206:8888=>socks: conn#2: [tunnel_in_proxy.go:135] Open------> socks
OpenChannel chisel
2024/01/07 01:35:50 client: tun: proxy#192.168.1.206:8888=>socks: conn#2: [tunnel_in_proxy.go:142] client send OpenChannel chisel
chan type:chisel extra:socks
chan type:chisel extra:socks wait PeersID [1] confim
recv channelOpenConfirmMsg confim
OpenChannel chisel get confirm
2024/01/07 01:35:50 client: tun: proxy#192.168.1.206:8888=>socks: conn#1: [tunnel_in_proxy.go:150] client OpenChannel chisel recv confirm
recv channelOpenConfirmMsg confim
OpenChannel chisel get confirm
2024/01/07 01:35:50 client: tun: proxy#192.168.1.206:8888=>socks: conn#2: [tunnel_in_proxy.go:150] client OpenChannel chisel recv confirm
2024/01/07 01:35:50 client: tun: proxy#192.168.1.206:8888=>socks: conn#2: [tunnel_in_proxy.go:155] Close (sent 478B received 4.05KB)
2024/01/07 01:35:50 client: tun: proxy#192.168.1.206:8888=>socks: conn#1: [tunnel_in_proxy.go:155] Close (sent 397B received 666B)
2024/01/07 01:35:53 client: tun: proxy#192.168.1.206:8888=>socks: conn#3: [tunnel_in_proxy.go:135] Open------> socks
OpenChannel chisel
2024/01/07 01:35:53 client: tun: proxy#192.168.1.206:8888=>socks: conn#3: [tunnel_in_proxy.go:142] client send OpenChannel chisel
chan type:chisel extra:socks
chan type:chisel extra:socks wait PeersID [0] confim
recv channelOpenConfirmMsg confim
OpenChannel chisel get confirm
2024/01/07 01:35:53 client: tun: proxy#192.168.1.206:8888=>socks: conn#3: [tunnel_in_proxy.go:150] client OpenChannel chisel recv confirm
2024/01/07 01:35:56 client: tun: proxy#192.168.1.206:8888=>socks: conn#4: [tunnel_in_proxy.go:135] Open------> socks
OpenChannel chisel
2024/01/07 01:35:56 client: tun: proxy#192.168.1.206:8888=>socks: conn#4: [tunnel_in_proxy.go:142] client send OpenChannel chisel
chan type:chisel extra:socks
chan type:chisel extra:socks wait PeersID [1] confim
recv channelOpenConfirmMsg confim
OpenChannel chisel get confirm
2024/01/07 01:35:56 client: tun: proxy#192.168.1.206:8888=>socks: conn#4: [tunnel_in_proxy.go:150] client OpenChannel chisel recv confirm
2024/01/07 01:35:56 client: tun: proxy#192.168.1.206:8888=>socks: conn#5: [tunnel_in_proxy.go:135] Open------> socks
OpenChannel chisel
2024/01/07 01:35:56 client: tun: proxy#192.168.1.206:8888=>socks: conn#5: [tunnel_in_proxy.go:142] client send OpenChannel chisel
chan type:chisel extra:socks
chan type:chisel extra:socks wait PeersID [2] confim
recv channelOpenConfirmMsg confim
OpenChannel chisel get confirm
2024/01/07 01:35:56 client: tun: proxy#192.168.1.206:8888=>socks: conn#5: [tunnel_in_proxy.go:150] client OpenChannel chisel recv confirm
2024/01/07 01:36:10 client: tun: [tunnel_out_ssh.go:20] handle ssh ping reply pong
2024/01/07 01:36:15 client: tun: proxy#192.168.1.206:8888=>socks: conn#6: [tunnel_in_proxy.go:135] Open------> socks
OpenChannel chisel
2024/01/07 01:36:15 client: tun: proxy#192.168.1.206:8888=>socks: conn#6: [tunnel_in_proxy.go:142] client send OpenChannel chisel
chan type:chisel extra:socks
chan type:chisel extra:socks wait PeersID [3] confim
recv channelOpenConfirmMsg confim
OpenChannel chisel get confirm
2024/01/07 01:36:15 client: tun: proxy#192.168.1.206:8888=>socks: conn#6: [tunnel_in_proxy.go:150] client OpenChannel chisel recv confirm
^C2024/01/07 01:36:16 client: tun: [tunnel.go:172] Unbound proxies
2024/01/07 01:36:16 client: tun: [tunnel.go:77] SSH cancelled
2024/01/07 01:36:16 client: tun: [tunnel.go:98] SSH disconnected
2024/01/07 01:36:16 client: [client_connect.go:132] Disconnected
2024/01/07 01:36:16 client: tun: proxy#192.168.1.206:8888=>socks: conn#5: [tunnel_in_proxy.go:155] Close (sent 2.61KB received 509B)
2024/01/07 01:36:16 client: [client_connect.go:54] Retrying in 100ms...
2024/01/07 01:36:16 client: [client_connect.go:59] Cancelled
第一步创建client
c, err := chclient.NewClient(&config)
client.sshConfig = &ssh.ClientConfig{
client.tunnel = tunnel.New(tunnel.Config{
第二步连接chisel server
2.1 c.Start(ctx)
2.1.1.1 d := websocket.Dialer{}
// NewClientConn establishes an authenticated SSH connection using c
// as the underlying transport. The Request and NewChannel channels
// must be serviced or the connection will hang.
func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) {
fullConf := *config
fullConf.SetDefaults()
if fullConf.HostKeyCallback == nil {
c.Close()
return nil, nil, nil, errors.New("ssh: must specify HostKeyCallback")
}
conn := &connection{
sshConn: sshConn{conn: c, user: fullConf.User},
}
if err := conn.clientHandshake(addr, &fullConf); err != nil {// 和server 端走ssh handshake
c.Close()
return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err)
}
conn.mux = newMux(conn.transport)创建mux 开启此ssh transport channel 以及读取conn的携程loop
return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
}
// newMux returns a mux that runs over the given connection.
func newMux(p packetConn) *mux {
m := &mux{
conn: p,
incomingChannels: make(chan NewChannel, chanSize),
globalResponses: make(chan interface{}, 1),
incomingRequests: make(chan *Request, chanSize),
errCond: newCond(),
}
if debugMux {
m.chanList.offset = atomic.AddUint32(&globalOff, 1)
}
go m.loop()
return m
}
go t.keepAliveLoop(c)开启 client到server 之间的心跳
func (t *Tunnel) keepAliveLoop(sshConn ssh.Conn) {
//ping forever
for {
time.Sleep(t.Config.KeepAlive)
_, b, err := sshConn.SendRequest("ping", true, nil)
if err != nil {
break
}
if len(b) > 0 && !bytes.Equal(b, []byte("pong")) {
t.Debugf("strange ping response")
break
}
}
//close ssh connection on abnormal ping
sshConn.Close()
}
2.1.1.4.2 go t.handleSSHRequests(reqs) 处理ssh ping 心跳请求
func (t *Tunnel) handleSSHRequests(reqs <-chan *ssh.Request) {
for r := range reqs {
switch r.Type {
case "ping":
t.Debugf("handle ssh ping reply pong")
r.Reply(true, []byte("pong"))
default:
t.Debugf("Unknown request: %s", r.Type)
}
}
}
func (t *Tunnel) handleSSHChannel(ch ssh.NewChannel) {
t.Debugf("process ssh channel forward -------------------------------")
remote := string(ch.ExtraData())
//extract protocol
hostPort, proto := settings.L4Proto(remote)
udp := proto == "udp"
socks := hostPort == "socks"
sshChan, reqs, err := ch.Accept()
stream := io.ReadWriteCloser(sshChan)
//cnet.MeterRWC(t.Logger.Fork("sshchan"), sshChan)
defer stream.Close()
go ssh.DiscardRequests(reqs)
l := t.Logger.Fork("conn#%d", t.connStats.New())
//ready to handle
t.connStats.Open()
l.Debugf("Open %s", t.connStats.String())
if socks {
err = t.handleSocks(stream)
} else if udp {
err = t.handleUDP(l, stream, hostPort)
} else {
l.Debugf("dial remote tcp %s", hostPort)
err = t.handleTCP(l, stream, hostPort)
}
t.connStats.Close()
l.Debugf("Close %s%s", t.connStats.String(), errmsg)
}
func (t *Tunnel) handleSocks(src io.ReadWriteCloser) error {
return t.socksServer.ServeConn(cnet.NewRWCConn(src))
}
func (t *Tunnel) handleTCP(l *cio.Logger, src io.ReadWriteCloser, hostPort string) error {
dst, err := net.Dial("tcp", hostPort)
s, r := cio.Pipe(src, dst)
l.Debugf("sent %s received %s", sizestr.ToString(s), sizestr.ToString(r))
return nil
}
c.tunnel.BindRemotes(ctx, clientInbound) --->BindRemotes converts the given remotes into proxies
p, err := NewProxy(t.Logger, t, t.proxyCount, remote)
go
p.Run(ctx) //初始化结束
p.runTCP(ctx)
src, err := p.tcp.Accept()
2.1.2.2.1.2
go p.pipeRemote(ctx, src)
2.1.2.2.1.2.1
sshConn := p.sshTun.getSSH(ctx)
2.1.2.2.1.2.2
dst, reqs, err := sshConn.OpenChannel("chisel", []byte(p.remote.Remote()))
2.1.2.2.1.2.3
s, r := cio.Pipe(src, dst)
数据业务流程:
浏览器访问192.168.1.4:8001端口时:浏览器将http请求封包send到192.168.1.206:8888 端口,此时listen 8888端口有新的conn
执行如下代码:
src, err := p.tcp.Accept()
go p.pipeRemote(ctx, src)
sshConn := p.sshTun.getSSH(ctx)
dst, reqs, err := sshConn.OpenChannel("chisel", []byte(p.remote.Remote()))
func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Request, error) {
ch, err := m.openChannel(chanType, extra)
return ch, ch.incomingRequests, nil
}
func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) {
ch := m.newChannel(chanType, channelOutbound, extra)
ch.maxIncomingPayload = channelMaxPacket
fmt.Printf("chan type:%s extra:%s\n", chanType, string(extra))
open := channelOpenMsg{
ChanType: chanType,
PeersWindow: ch.myWindow,
MaxPacketSize: ch.maxIncomingPayload,
TypeSpecificData: extra,
PeersID: ch.localId,
}
err := m.sendMessage(open)
fmt.Printf("chan type:%s extra:%s wait PeersID [%d] confim\n", chanType, string(extra), ch.localId)
switch msg := (<-ch.msg).(type) {
case *channelOpenConfirmMsg:
fmt.Printf("recv channelOpenConfirmMsg confim\n")
return ch, nil
----------------------
}
}
s, r := cio.Pipe(src, dst)
当client调用openChannel
m.sendMessage(open) 发送openchannel 消息时,会在
(<-ch.msg).(type)等待消息openchannel响应
来看server 怎样响应;先看server 执行流程
s, err := chserver.NewServer(config)
err := s.StartContext(ctx, *host, *port)
l, err := s.listener(host, port)
h := http.Handler(http.HandlerFunc(s.handleClientHandler))
s.httpServer.GoServe(ctx, l, h)
监听8888 端口的http回调函数为handleClientHandler
handleClientHandler处理逻辑为:
upgrade := strings.ToLower(r.Header.Get("Upgrade"))
protocol := r.Header.Get("Sec-WebSocket-Protocol")
if upgrade == "websocket" {
if protocol == chshare.ProtocolVersion {
s.handleWebsocket(w, r)
也就是在http里面执行upgrade websocket

handleWebsocket(w http.ResponseWriter, req *http.Request)逻辑为
// handleWebsocket is responsible for handling the websocket connection
func (s *Server) handleWebsocket(w http.ResponseWriter, req *http.Request) {
id := atomic.AddInt32(&s.sessCount, 1)
l := s.Fork("session#%d", id)
wsConn, err := upgrader.Upgrade(w, req, nil)
conn := cnet.NewWebSocketConn(wsConn)
// perform SSH handshake on net.Conn
l.Debugf("Handshaking with %s...", req.RemoteAddr)
sshConn, chans, reqs, err := ssh.NewServerConn(conn, s.sshConfig)
// chisel server handshake (reverse of client handshake)
// verify configuration
l.Debugf("Verifying configuration")
// wait for request, with timeout
var r *ssh.Request
select {
case r = <-reqs:
case <-time.After(settings.EnvDuration("CONFIG_TIMEOUT", 10*time.Second)):
l.Debugf("Timeout waiting for configuration")
sshConn.Close()
return
}
c, err := settings.DecodeConfig(r.Payload)
if err != nil {
failed(s.Errorf("invalid config"))
return
}
l.Debugf("DecodeConfig %#v", c)
//successfuly validated config!
r.Reply(true, nil)
//tunnel per ssh connection
tunnel := tunnel.New(tunnel.Config{
Logger: l,
Inbound: s.config.Reverse,
Outbound: true, //server always accepts outbound
Socks: s.config.Socks5,
KeepAlive: s.config.KeepAlive,
})
l.Debugf("tunnel Config %#v", tunnel)
//bind
eg, ctx := errgroup.WithContext(req.Context())
//connected, handover ssh connection for tunnel to use, and block
eg.Go tunnel.BindSSH(ctx, sshConn, reqs, chans)
eg.Go tunnel.BindRemotes(ctx, serverInbound)
err = eg.Wait()
if err != nil && !strings.HasSuffix(err.Error(), "EOF") {
l.Debugf("Closed connection (%s)", err)
} else {
l.Debugf("Closed connection")
}
}
// NewServerConn starts a new SSH server with c as the underlying
// transport. It starts with a handshake and, if the handshake is
// unsuccessful, it closes the connection and returns an error. The
// Request and NewChannel channels must be serviced, or the connection
// will hang.
//
// The returned error may be of type *ServerAuthError for
// authentication errors.
func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
fullConf := *config
fullConf.SetDefaults()
s := &connection{
sshConn: sshConn{conn: c},
}
perms, err := s.serverHandshake(&fullConf)
return &ServerConn{s, perms}, s.mux.incomingChannels, s.mux.incomingRequests, nil
}
// handshake performs key exchange and user authentication.
func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) {
s.serverVersion = []byte(config.ServerVersion)
var err error
s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion)
tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */)
s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config)
if err := s.transport.waitSession(); err != nil {
}
// We just did the key change, so the session ID is established.
s.sessionID = s.transport.getSessionID()
var packet []byte
if packet, err = s.transport.readPacket(); err != nil {
}
var serviceRequest serviceRequestMsg
if err = Unmarshal(packet, &serviceRequest); err != nil {
}
serviceAccept := serviceAcceptMsg{
Service: serviceUserAuth,
}
if err := s.transport.writePacket(Marshal(&serviceAccept)); err != nil {
}
perms, err := s.serverAuthenticate(config)
s.mux = newMux(s.transport)
return perms, err
}
func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ServerConfig) *handshakeTransport {
t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
t.hostKeys = config.hostKeys
go t.readLoop()
go t.kexLoop()
return t
}
// waitSession waits for the session to be established. This should be
// the first thing to call after instantiating handshakeTransport.
func (t *handshakeTransport) waitSession() error {
p, err := t.readPacket()
if err != nil {
return err
}
if p[0] != msgNewKeys {
return fmt.Errorf("ssh: first packet should be msgNewKeys")
}
return nil
}
在回到 当client调用openChannel 发送给时, server 处理逻辑是:tcp--->http--->--->websockt--->ssh隧道走完。
此时server 端只需要从ssh 隧道读取数据即可:读取函数在初始化mux时,已经开启goruntime来处理。
// loop runs the connection machine. It will process packets until an
// error is encountered. To synchronize on loop exit, use mux.Wait.
func (m *mux) loop() {
var err error
for err == nil {
err = m.onePacket()
}
}
// onePacket reads and processes one packet.
func (m *mux) onePacket() error {
packet, err := m.conn.readPacket()
if debugMux {
if packet[0] == msgChannelData || packet[0] == msgChannelExtendedData {
log.Printf("decoding(%d): data packet - %d bytes", m.chanList.offset, len(packet))
} else {
p, _ := decode(packet)
log.Printf("decoding(%d): %d %#v - %d bytes", m.chanList.offset, packet[0], p, len(packet))
}
}
switch packet[0] {
case msgChannelOpen:
return m.handleChannelOpen(packet)
case msgGlobalRequest, msgRequestSuccess, msgRequestFailure:
return m.handleGlobalPacket(packet)
}
// assume a channel packet.
if len(packet) < 5 {
return parseError(packet[0])
}
id := binary.BigEndian.Uint32(packet[1:])
ch := m.chanList.getChan(id)
if ch == nil {
return m.handleUnknownChannelPacket(id, packet)
}
return ch.handlePacket(packet)
}
对于openchannel 报文,则执行handleChannelOpen
// handleChannelOpen schedules a channel to be Accept()ed.
func (m *mux) handleChannelOpen(packet []byte) error {
var msg channelOpenMsg
if err := Unmarshal(packet, &msg); err != nil {
return err
}
if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {
failMsg := channelOpenFailureMsg{
PeersID: msg.PeersID,
Reason: ConnectionFailed,
Message: "invalid request",
Language: "en_US.UTF-8",
}
return m.sendMessage(failMsg)
}
fmt.Printf("chan type:%s type spdata:%s peerid:%d \n", msg.ChanType, string(msg.TypeSpecificData), msg.PeersID)
c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData)
c.remoteId = msg.PeersID
c.maxRemotePayload = msg.MaxPacketSize
c.remoteWin.add(msg.PeersWindow)
m.incomingChannels <- c
return nil
}
最后将请求报文放在 m.incomingChannels <- c; m.incomingChannels 数据在 go t.handleSSHChannel(ch) 处理。
此时就会调用 sshChan, reqs, err := ch.Accept(); 发送openchannel 响应confirm报文。
func (ch *channel) Accept() (Channel, <-chan *Request, error) {
if ch.decided {
return nil, nil, errDecidedAlready
}
ch.maxIncomingPayload = channelMaxPacket
confirm := channelOpenConfirmMsg{
PeersID: ch.remoteId,
MyID: ch.localId,
MyWindow: ch.myWindow,
MaxPacketSize: ch.maxIncomingPayload,
}
ch.decided = true
fmt.Printf("channel open server confirm msg %#v \n", confirm)
if err := ch.sendMessage(confirm); err != nil {
return nil, nil, err
}
return ch, ch.incomingRequests, nil
}
此时客户端从openchannel 返回开始转发一开始浏览器发送的数据到ssh隧道。
同时隧道server端开始接收这次数据,处理。
如果是socks 则调用 err = t.handleSocks(stream) --->t.socksServer.ServeConn(cnet.NewRWCConn(src)) 转发浏览器的请求
// ServeConn is used to serve a single connection.
func (s *Server) ServeConn(conn net.Conn) error {
defer conn.Close()
bufConn := bufio.NewReader(conn)
// Read the version byte
version := []byte{0}
if _, err := bufConn.Read(version); err != nil {
s.config.Logger.Printf("[ERR] socks: Failed to get version byte: %v", err)
return err
}
// Ensure we are compatible
if version[0] != socks5Version {
err := fmt.Errorf("Unsupported SOCKS version: %v", version)
s.config.Logger.Printf("[ERR] socks: %v", err)
return err
}
// Authenticate the connection
authContext, err := s.authenticate(conn, bufConn)
if err != nil {
err = fmt.Errorf("Failed to authenticate: %v", err)
s.config.Logger.Printf("[ERR] socks: %v", err)
return err
}
request, err := NewRequest(bufConn)
if err != nil {
if err == unrecognizedAddrType {
if err := sendReply(conn, addrTypeNotSupported, nil); err != nil {
return fmt.Errorf("Failed to send reply: %v", err)
}
}
return fmt.Errorf("Failed to read destination address: %v", err)
}
request.AuthContext = authContext
if client, ok := conn.RemoteAddr().(*net.TCPAddr); ok {
request.RemoteAddr = &AddrSpec{IP: client.IP, Port: client.Port}
}
// Process the client request
if err := s.handleRequest(request, conn); err != nil {
err = fmt.Errorf("Failed to handle request: %v", err)
s.config.Logger.Printf("[ERR] socks: %v", err)
return err
}
return nil
}
server log:
查看代码
[root@localhost chisel-1.9.1]# ./chisel server -v --host 192.168.1.207 -p 12345 --socks5
2024/01/07 01:26:01 server: [server.go:163] Fingerprint taaVApzz3e+BWzXBeD1JYdWSTUzMkfQMhsgDxH3R0Uk=
2024/01/07 01:26:01 server: [server_listen.go:58] Listening on http://192.168.1.207:12345
2024/01/07 01:26:20 server: [server_handler.go:22] User-Agent: Go-http-client/1.1
2024/01/07 01:26:20 server: [server_handler.go:22] Connection: Upgrade
2024/01/07 01:26:20 server: [server_handler.go:22] Sec-Websocket-Key: Hgm/F2A6GpsCPtEQ2OlXhQ==
2024/01/07 01:26:20 server: [server_handler.go:22] Sec-Websocket-Protocol: chisel-v3
2024/01/07 01:26:20 server: [server_handler.go:22] Sec-Websocket-Version: 13
2024/01/07 01:26:20 server: [server_handler.go:22] Upgrade: websocket
2024/01/07 01:26:20 server: session#1: [server_handler.go:67] Handshaking with 192.168.1.206:43536...
versionline:[83 83 72 45 99 104 105 115 101 108 45 118 51 45 115 101 114 118 101 114] (SSH-chisel-v3-server)
resp versionline:[83 83 72 45 99 104 105 115 101 108 45 118 51 45 99 108 105 101 110 116] (SSH-chisel-v3-client)
2024/01/07 01:26:20 server: session#1: [server_handler.go:86] Verifying configuration
2024/01/07 01:26:20 server: session#1: [server_handler.go:109] DecodeConfig &settings.Config{Version:"0.0.0-src", Remotes:settings.Remotes{(*settings.Remote)(0xc0000bdb20)}}
2024/01/07 01:26:20 server: session#1: tun: [tunnel.go:67] Created (SOCKS enabled)
2024/01/07 01:26:20 server: session#1: [server_handler.go:152] tunnel Config &tunnel.Tunnel{Config:tunnel.Config{Logger:(*cio.Logger)(0xc0000f73b0), Inbound:false, Outbound:true, Socks:true, KeepAlive:25000000000}, activeConnMut:sync.RWMutex{w:sync.Mutex{state:0, sema:0x0}, writerSem:0x0, readerSem:0x0, readerCount:atomic.Int32{_:atomic.noCopy{}, v:0}, readerWait:atomic.Int32{_:atomic.noCopy{}, v:0}}, activatingConn:tunnel.waitGroup{inner:sync.WaitGroup{noCopy:sync.noCopy{}, state:atomic.Uint64{_:atomic.noCopy{}, _:atomic.align64{}, v:0x100000000}, sema:0x0}, n:1}, activeConn:ssh.Conn(nil), proxyCount:0, connStats:cnet.ConnCount{count:0, open:0}, socksServer:(*socks5.Server)(0xc0000e8a00)}
2024/01/07 01:26:20 server: session#1: tun: [tunnel.go:96] SSH connected
chan type:chisel type spdata:socks peerid:0
2024/01/07 01:26:44 server: session#1: tun: [tunnel_out_ssh.go:40] process ssh channel forward -------------------------------
channel open server confirm msg ssh.channelOpenConfirmMsg{PeersID:0x0, MyID:0x0, MyWindow:0x200000, MaxPacketSize:0x8000, TypeSpecificData:[]uint8(nil)}
2024/01/07 01:26:44 server: session#1: tun: conn#1: [tunnel_out_ssh.go:63] Open [1/1]
chan type:chisel type spdata:socks peerid:1
2024/01/07 01:26:44 server: session#1: tun: [tunnel_out_ssh.go:40] process ssh channel forward -------------------------------
channel open server confirm msg ssh.channelOpenConfirmMsg{PeersID:0x1, MyID:0x1, MyWindow:0x200000, MaxPacketSize:0x8000, TypeSpecificData:[]uint8(nil)}
2024/01/07 01:26:44 server: session#1: tun: conn#2: [tunnel_out_ssh.go:63] Open [2/2]
chan type:chisel type spdata:socks peerid:2
2024/01/07 01:26:44 server: session#1: tun: [tunnel_out_ssh.go:40] process ssh channel forward -------------------------------
channel open server confirm msg ssh.channelOpenConfirmMsg{PeersID:0x2, MyID:0x2, MyWindow:0x200000, MaxPacketSize:0x8000, TypeSpecificData:[]uint8(nil)}
2024/01/07 01:26:44 server: session#1: tun: conn#3: [tunnel_out_ssh.go:63] Open [3/3]
2024/01/07 01:26:45 server: session#1: tun: [tunnel_out_ssh.go:20] handle ssh ping reply pong
chan type:chisel type spdata:socks peerid:3
2024/01/07 01:26:46 server: session#1: tun: [tunnel_out_ssh.go:40] process ssh channel forward -------------------------------
channel open server confirm msg ssh.channelOpenConfirmMsg{PeersID:0x3, MyID:0x3, MyWindow:0x200000, MaxPacketSize:0x8000, TypeSpecificData:[]uint8(nil)}
2024/01/07 01:26:46 server: session#1: tun: conn#4: [tunnel_out_ssh.go:63] Open [4/4]
chan type:chisel type spdata:socks peerid:4
2024/01/07 01:26:46 server: session#1: tun: [tunnel_out_ssh.go:40] process ssh channel forward -------------------------------
channel open server confirm msg ssh.channelOpenConfirmMsg{PeersID:0x4, MyID:0x4, MyWindow:0x200000, MaxPacketSize:0x8000, TypeSpecificData:[]uint8(nil)}
2024/01/07 01:26:46 server: session#1: tun: conn#5: [tunnel_out_ssh.go:63] Open [5/5]
chan type:chisel type spdata:socks peerid:5
明天继续整理格式;并学习go ctx等
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2023-01-06 tcp_ack 以及拥塞控制
2022-01-06 VFS 虚拟文件系统 转载
2022-01-06 虚拟文件系统
2020-01-06 调试 工具
2020-01-06 sed1
2020-01-06 awk1
2020-01-06 共享内存 设计原理-shm