mirror of https://github.com/1Panel-dev/1Panel
ssongliu
4 months ago
36 changed files with 411 additions and 116 deletions
@ -1,5 +1,15 @@
|
||||
package dto |
||||
|
||||
type SearchWithPage struct { |
||||
PageInfo |
||||
Info string `json:"info"` |
||||
} |
||||
|
||||
type PageInfo struct { |
||||
Page int `json:"page" validate:"required,number"` |
||||
PageSize int `json:"pageSize" validate:"required,number"` |
||||
} |
||||
|
||||
type PageResult struct { |
||||
Total int64 `json:"total"` |
||||
Items interface{} `json:"items"` |
@ -1,11 +0,0 @@
|
||||
package dto |
||||
|
||||
type SearchWithPage struct { |
||||
PageInfo |
||||
Info string `json:"info"` |
||||
} |
||||
|
||||
type PageInfo struct { |
||||
Page int `json:"page" validate:"required,number"` |
||||
PageSize int `json:"pageSize" validate:"required,number"` |
||||
} |
@ -0,0 +1,165 @@
|
||||
package qqwry |
||||
|
||||
import ( |
||||
"encoding/binary" |
||||
"net" |
||||
"strings" |
||||
|
||||
"github.com/1Panel-dev/1Panel/cmd/server/qqwry" |
||||
"golang.org/x/text/encoding/simplifiedchinese" |
||||
) |
||||
|
||||
const ( |
||||
indexLen = 7 |
||||
redirectMode1 = 0x01 |
||||
redirectMode2 = 0x02 |
||||
) |
||||
|
||||
var IpCommonDictionary []byte |
||||
|
||||
type QQwry struct { |
||||
Data []byte |
||||
Offset int64 |
||||
} |
||||
|
||||
func NewQQwry() (*QQwry, error) { |
||||
IpCommonDictionary := qqwry.QQwryByte |
||||
return &QQwry{Data: IpCommonDictionary}, nil |
||||
} |
||||
|
||||
// readData 从文件中读取数据
|
||||
func (q *QQwry) readData(num int, offset ...int64) (rs []byte) { |
||||
if len(offset) > 0 { |
||||
q.setOffset(offset[0]) |
||||
} |
||||
nums := int64(num) |
||||
end := q.Offset + nums |
||||
dataNum := int64(len(q.Data)) |
||||
if q.Offset > dataNum { |
||||
return nil |
||||
} |
||||
|
||||
if end > dataNum { |
||||
end = dataNum |
||||
} |
||||
rs = q.Data[q.Offset:end] |
||||
q.Offset = end |
||||
return |
||||
} |
||||
|
||||
// setOffset 设置偏移量
|
||||
func (q *QQwry) setOffset(offset int64) { |
||||
q.Offset = offset |
||||
} |
||||
|
||||
// Find ip地址查询对应归属地信息
|
||||
func (q *QQwry) Find(ip string) (res ResultQQwry) { |
||||
res = ResultQQwry{} |
||||
res.IP = ip |
||||
if strings.Count(ip, ".") != 3 { |
||||
return res |
||||
} |
||||
offset := q.searchIndex(binary.BigEndian.Uint32(net.ParseIP(ip).To4())) |
||||
if offset <= 0 { |
||||
return |
||||
} |
||||
|
||||
var area []byte |
||||
mode := q.readMode(offset + 4) |
||||
if mode == redirectMode1 { |
||||
countryOffset := q.readUInt24() |
||||
mode = q.readMode(countryOffset) |
||||
if mode == redirectMode2 { |
||||
c := q.readUInt24() |
||||
area = q.readString(c) |
||||
} else { |
||||
area = q.readString(countryOffset) |
||||
} |
||||
} else if mode == redirectMode2 { |
||||
countryOffset := q.readUInt24() |
||||
area = q.readString(countryOffset) |
||||
} else { |
||||
area = q.readString(offset + 4) |
||||
} |
||||
|
||||
enc := simplifiedchinese.GBK.NewDecoder() |
||||
res.Area, _ = enc.String(string(area)) |
||||
|
||||
return |
||||
} |
||||
|
||||
type ResultQQwry struct { |
||||
IP string `json:"ip"` |
||||
Area string `json:"area"` |
||||
} |
||||
|
||||
// readMode 获取偏移值类型
|
||||
func (q *QQwry) readMode(offset uint32) byte { |
||||
mode := q.readData(1, int64(offset)) |
||||
return mode[0] |
||||
} |
||||
|
||||
// readString 获取字符串
|
||||
func (q *QQwry) readString(offset uint32) []byte { |
||||
q.setOffset(int64(offset)) |
||||
data := make([]byte, 0, 30) |
||||
for { |
||||
buf := q.readData(1) |
||||
if buf[0] == 0 { |
||||
break |
||||
} |
||||
data = append(data, buf[0]) |
||||
} |
||||
return data |
||||
} |
||||
|
||||
// searchIndex 查找索引位置
|
||||
func (q *QQwry) searchIndex(ip uint32) uint32 { |
||||
header := q.readData(8, 0) |
||||
|
||||
start := binary.LittleEndian.Uint32(header[:4]) |
||||
end := binary.LittleEndian.Uint32(header[4:]) |
||||
|
||||
for { |
||||
mid := q.getMiddleOffset(start, end) |
||||
buf := q.readData(indexLen, int64(mid)) |
||||
_ip := binary.LittleEndian.Uint32(buf[:4]) |
||||
|
||||
if end-start == indexLen { |
||||
offset := byteToUInt32(buf[4:]) |
||||
buf = q.readData(indexLen) |
||||
if ip < binary.LittleEndian.Uint32(buf[:4]) { |
||||
return offset |
||||
} |
||||
return 0 |
||||
} |
||||
|
||||
if _ip > ip { |
||||
end = mid |
||||
} else if _ip < ip { |
||||
start = mid |
||||
} else if _ip == ip { |
||||
return byteToUInt32(buf[4:]) |
||||
} |
||||
} |
||||
} |
||||
|
||||
// readUInt24
|
||||
func (q *QQwry) readUInt24() uint32 { |
||||
buf := q.readData(3) |
||||
return byteToUInt32(buf) |
||||
} |
||||
|
||||
// getMiddleOffset
|
||||
func (q *QQwry) getMiddleOffset(start uint32, end uint32) uint32 { |
||||
records := ((end - start) / indexLen) >> 1 |
||||
return start + records*indexLen |
||||
} |
||||
|
||||
// byteToUInt32 将 byte 转换为uint32
|
||||
func byteToUInt32(data []byte) uint32 { |
||||
i := uint32(data[0]) & 0xff |
||||
i |= (uint32(data[1]) << 8) & 0xff00 |
||||
i |= (uint32(data[2]) << 16) & 0xff0000 |
||||
return i |
||||
} |
@ -0,0 +1,142 @@
|
||||
package ssh |
||||
|
||||
import ( |
||||
"bytes" |
||||
"fmt" |
||||
"io" |
||||
"strings" |
||||
"sync" |
||||
"time" |
||||
|
||||
gossh "golang.org/x/crypto/ssh" |
||||
) |
||||
|
||||
type ConnInfo struct { |
||||
User string `json:"user"` |
||||
Addr string `json:"addr"` |
||||
Port int `json:"port"` |
||||
AuthMode string `json:"authMode"` |
||||
Password string `json:"password"` |
||||
PrivateKey []byte `json:"privateKey"` |
||||
PassPhrase []byte `json:"passPhrase"` |
||||
DialTimeOut time.Duration `json:"dialTimeOut"` |
||||
|
||||
Client *gossh.Client `json:"client"` |
||||
Session *gossh.Session `json:"session"` |
||||
LastResult string `json:"lastResult"` |
||||
} |
||||
|
||||
func (c *ConnInfo) NewClient() (*ConnInfo, error) { |
||||
if strings.Contains(c.Addr, ":") { |
||||
c.Addr = fmt.Sprintf("[%s]", c.Addr) |
||||
} |
||||
config := &gossh.ClientConfig{} |
||||
config.SetDefaults() |
||||
addr := fmt.Sprintf("%s:%d", c.Addr, c.Port) |
||||
config.User = c.User |
||||
if c.AuthMode == "password" { |
||||
config.Auth = []gossh.AuthMethod{gossh.Password(c.Password)} |
||||
} else { |
||||
signer, err := makePrivateKeySigner(c.PrivateKey, c.PassPhrase) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
config.Auth = []gossh.AuthMethod{gossh.PublicKeys(signer)} |
||||
} |
||||
if c.DialTimeOut == 0 { |
||||
c.DialTimeOut = 5 * time.Second |
||||
} |
||||
config.Timeout = c.DialTimeOut |
||||
|
||||
config.HostKeyCallback = gossh.InsecureIgnoreHostKey() |
||||
proto := "tcp" |
||||
if strings.Contains(c.Addr, ":") { |
||||
proto = "tcp6" |
||||
} |
||||
client, err := gossh.Dial(proto, addr, config) |
||||
if nil != err { |
||||
return c, err |
||||
} |
||||
c.Client = client |
||||
return c, nil |
||||
} |
||||
|
||||
func (c *ConnInfo) Run(shell string) (string, error) { |
||||
if c.Client == nil { |
||||
if _, err := c.NewClient(); err != nil { |
||||
return "", err |
||||
} |
||||
} |
||||
session, err := c.Client.NewSession() |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
defer session.Close() |
||||
buf, err := session.CombinedOutput(shell) |
||||
|
||||
c.LastResult = string(buf) |
||||
return c.LastResult, err |
||||
} |
||||
|
||||
func (c *ConnInfo) Close() { |
||||
_ = c.Client.Close() |
||||
} |
||||
|
||||
type SshConn struct { |
||||
StdinPipe io.WriteCloser |
||||
ComboOutput *wsBufferWriter |
||||
Session *gossh.Session |
||||
} |
||||
|
||||
func (c *ConnInfo) NewSshConn(cols, rows int) (*SshConn, error) { |
||||
sshSession, err := c.Client.NewSession() |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
stdinP, err := sshSession.StdinPipe() |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
comboWriter := new(wsBufferWriter) |
||||
sshSession.Stdout = comboWriter |
||||
sshSession.Stderr = comboWriter |
||||
|
||||
modes := gossh.TerminalModes{ |
||||
gossh.ECHO: 1, |
||||
gossh.TTY_OP_ISPEED: 14400, |
||||
gossh.TTY_OP_OSPEED: 14400, |
||||
} |
||||
if err := sshSession.RequestPty("xterm", rows, cols, modes); err != nil { |
||||
return nil, err |
||||
} |
||||
if err := sshSession.Shell(); err != nil { |
||||
return nil, err |
||||
} |
||||
return &SshConn{StdinPipe: stdinP, ComboOutput: comboWriter, Session: sshSession}, nil |
||||
} |
||||
|
||||
func (s *SshConn) Close() { |
||||
if s.Session != nil { |
||||
s.Session.Close() |
||||
} |
||||
} |
||||
|
||||
type wsBufferWriter struct { |
||||
buffer bytes.Buffer |
||||
mu sync.Mutex |
||||
} |
||||
|
||||
func (w *wsBufferWriter) Write(p []byte) (int, error) { |
||||
w.mu.Lock() |
||||
defer w.mu.Unlock() |
||||
return w.buffer.Write(p) |
||||
} |
||||
|
||||
func makePrivateKeySigner(privateKey []byte, passPhrase []byte) (gossh.Signer, error) { |
||||
if len(passPhrase) != 0 { |
||||
return gossh.ParsePrivateKeyWithPassphrase(privateKey, passPhrase) |
||||
} |
||||
return gossh.ParsePrivateKey(privateKey) |
||||
} |
Loading…
Reference in new issue