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 c.connectionLoop(ctx)
       2.1.1.1  d := websocket.Dialer{} 
          2.1.1.2wsConn, _, err := d.DialContext(ctx, c.server, c.config.Headers)
       2.1.1.3  sshConn, chans, reqs, err := ssh.NewClientConn(conn, "", c.sshConfig)
// 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
}
              
      2.1.1.4err = c.tunnel.BindSSH(ctx, sshConn, reqs, chans)
           2.1.1.4.1  go t.keepAliveLoop(c)
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)
        }
    }
  }
              
        2.1.1.4.3  go t.handleSSHChannels(chans)
            2.1.1.4.3.1  go t.handleSSHChannel(ch)

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
}
 
 
  2.1.2  c.tunnel.BindRemotes(ctx, clientInbound)  --->BindRemotes converts the given remotes into proxies
    2.1.2.1  p, err := NewProxy(t.Logger, t, t.proxyCount, remote)
    2.1.2.2   go p.Run(ctx) //初始化结束
      2.1.2.2.1  p.runTCP(ctx)
        2.1.2.2.1.1  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初始化 server conn时会执行upgrade websockt 以及基于websockt 进行ssh 协商密钥
// 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等

 

posted @ 2024-01-06 14:46  codestacklinuxer  阅读(28)  评论(0编辑  收藏  举报