目标:golang服务,准备获取ip:port的banner信息.如果ip:port为http,即可获取http响应,如果为ssh服务,即可获取ssh服务输出信息.如版本信息等.前置条件:对应tcpAddr可以访问(该http服务输出helloworld)问题:通过代码conn,err:=net.DialTimeout("tcp",tcpAddr.String(),timeout)iferr!=nil{returnfalse}reply:=make([]byte,4096)conn.Read(reply)conn.SetReadDeadline(time.Now().Add(time.Second))byte,err:=ioutil.ReadAll(conn)fmt.Println("srvreply:"+string(byte))deferconn.Close()发现线程阻塞到read上.请问如何避免这种阻塞,并能获取到对应endpointbanner信息?追加:如果先SetReadDeadline,会在超时后解除阻塞.但获取到的reply为空.
2 回答
慕侠2389804
TA贡献1719条经验 获得超6个赞
假定你要做一个SSH与HTTP的服务扫描器,那你可能没有发现SSH与HTTP服务对于客户端的区别。对SSH服务来说,客户端完成TCP连接后,就会收到服务器发送的banner信息,类似这样的SSH-2.0-xxxxxx\r\n...但是HTTP服务器不一样,客户端完成TCP连接后,必须发送一个请求,如HEAD/HTTP/1.0\r\n\r\n服务器才会返回内容,如HTTP/1.0404NotFound\r\n...下面是参考代码packagemainimport("bufio""bytes""fmt""io""net""sync""time")//假定是SSH服务。//返回banner第一行。funcassume_ssh(addressstring)(string,error){conn,err:=net.DialTimeout("tcp",address,time.Second*10)iferr!=nil{return"",err}deferconn.Close()tcpconn:=conn.(*net.TCPConn)//设置读取的超时时间tcpconn.SetReadDeadline(time.Now().Add(time.Second*5))reader:=bufio.NewReader(conn)returnreader.ReadString('\n')}funcsplit_http_head(data[]byte,atEOFbool)(advanceint,token[]byte,errerror){head_end:=bytes.Index(data,[]byte("\r\n\r\n"))ifhead_end==-1{return0,nil,nil}returnhead_end+4,data[:head_end+4],nil}//假定是HTTP服务。//返回"/"HTTP返回头。funcassume_http(addressstring)(string,error){conn,err:=net.DialTimeout("tcp",address,time.Second*10)iferr!=nil{return"",err}deferconn.Close()tcpconn:=conn.(*net.TCPConn)//设置写的超时时间tcpconn.SetWriteDeadline(time.Now().Add(time.Second*5))if_,err:=conn.Write([]byte("HEAD/HTTP/1.0\r\n\r\n"));err!=nil{return"",err}//设置读的超时时间tcpconn.SetReadDeadline(time.Now().Add(time.Second*5))scanner:=bufio.NewScanner(conn)scanner.Split(split_http_head)ifscanner.Scan(){returnscanner.Text(),nil}err=scanner.Err()iferr==nil{err=io.EOF}return"",err}funccheck_address(addressstring){result:=make(chanstring,2)done:=make(chanint,1)vargsync.WaitGroupg.Add(2)gofunc(){ifr,e:=assume_ssh(address);e==nil{result<-fmt.Sprintf("SSH:%s",r)}g.Done()}()gofunc(){ifr,e:=assume_http(address);e==nil{result<-fmt.Sprintf("HTTP:%s",r)}g.Done()}()gofunc(){g.Wait()done<-1}()select{case<-done:fmt.Printf("#%s\n无结果",address)caser:=<-result:fmt.Printf("#%s\n%s",address,r)}}funcmain(){check_address("github.com:80")check_address("github.com:22")}运行结果#github.com:80HTTP:HTTP/1.1301MovedPermanentlyContent-length:0Location:https:///Connection:close#github.com:22SSH:SSH-2.0-libssh_0.7.0
Qyouu
TA贡献1786条经验 获得超11个赞
tcp在传输层,http在应用层是否能这样直接使用呢?这个存在疑问。因为我是没有这样用过,基本上服务端是http,client就使用http协议去对接。tcp也一样。
添加回答
举报
0/150
提交
取消
