mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 05:56:46 +08:00
109 lines
2.7 KiB
Go
109 lines
2.7 KiB
Go
package memcached
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"net"
|
||
"strings"
|
||
"time"
|
||
|
||
"github.com/shadow1ng/fscan/common"
|
||
"github.com/shadow1ng/fscan/plugins/base"
|
||
)
|
||
|
||
// MemcachedConnection Memcached连接包装器
|
||
type MemcachedConnection struct {
|
||
client net.Conn
|
||
target string
|
||
}
|
||
|
||
// MemcachedConnector Memcached连接器实现
|
||
type MemcachedConnector struct {
|
||
host string
|
||
port string
|
||
}
|
||
|
||
// NewMemcachedConnector 创建Memcached连接器
|
||
func NewMemcachedConnector() *MemcachedConnector {
|
||
return &MemcachedConnector{}
|
||
}
|
||
|
||
// Connect 连接到Memcached服务
|
||
func (c *MemcachedConnector) Connect(ctx context.Context, info *common.HostInfo) (interface{}, error) {
|
||
c.host = info.Host
|
||
c.port = info.Ports
|
||
|
||
target := fmt.Sprintf("%s:%s", c.host, c.port)
|
||
timeout := time.Duration(common.Timeout) * time.Second
|
||
|
||
// 建立TCP连接
|
||
client, err := common.WrapperTcpWithTimeout("tcp", target, timeout)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("Memcached连接失败: %v", err)
|
||
}
|
||
|
||
return &MemcachedConnection{
|
||
client: client,
|
||
target: target,
|
||
}, nil
|
||
}
|
||
|
||
// Authenticate 认证 - Memcached通常无认证,检查未授权访问
|
||
func (c *MemcachedConnector) Authenticate(ctx context.Context, conn interface{}, cred *base.Credential) error {
|
||
memcachedConn, ok := conn.(*MemcachedConnection)
|
||
if !ok {
|
||
return fmt.Errorf("无效的连接类型")
|
||
}
|
||
|
||
// 在goroutine中进行操作,支持Context取消
|
||
resultChan := make(chan error, 1)
|
||
|
||
go func() {
|
||
// 设置操作超时
|
||
timeout := time.Duration(common.Timeout) * time.Second
|
||
if err := memcachedConn.client.SetDeadline(time.Now().Add(timeout)); err != nil {
|
||
resultChan <- fmt.Errorf("设置超时失败: %v", err)
|
||
return
|
||
}
|
||
|
||
// 发送stats命令测试连接
|
||
if _, err := memcachedConn.client.Write([]byte("stats\n")); err != nil {
|
||
resultChan <- fmt.Errorf("发送命令失败: %v", err)
|
||
return
|
||
}
|
||
|
||
// 读取响应
|
||
buffer := make([]byte, 1024)
|
||
n, err := memcachedConn.client.Read(buffer)
|
||
if err != nil {
|
||
resultChan <- fmt.Errorf("读取响应失败: %v", err)
|
||
return
|
||
}
|
||
|
||
// 检查响应是否包含Memcached统计信息
|
||
response := string(buffer[:n])
|
||
if strings.Contains(response, "STAT") {
|
||
// 未授权访问成功
|
||
resultChan <- nil
|
||
return
|
||
}
|
||
|
||
resultChan <- fmt.Errorf("Memcached服务无响应或不可访问")
|
||
}()
|
||
|
||
// 等待操作结果或Context取消
|
||
select {
|
||
case err := <-resultChan:
|
||
return err
|
||
case <-ctx.Done():
|
||
return fmt.Errorf("Memcached操作超时: %v", ctx.Err())
|
||
}
|
||
}
|
||
|
||
// Close 关闭连接
|
||
func (c *MemcachedConnector) Close(conn interface{}) error {
|
||
if memcachedConn, ok := conn.(*MemcachedConnection); ok && memcachedConn.client != nil {
|
||
return memcachedConn.client.Close()
|
||
}
|
||
return nil
|
||
} |