diff --git a/admin/colony.html b/admin/colony.html
index dcdb61c..229df35 100644
--- a/admin/colony.html
+++ b/admin/colony.html
@@ -120,7 +120,7 @@
for (var i = 0; i < data.length; i++) {
_h += '
{{$e.setting_name}} |
{{$e.setting_dis}} |
- |
+ |
{{if ne $e.info ""}}
已配置
{{else}}
diff --git a/config.ini b/config.ini
index 3490145..227ce21 100644
--- a/config.ini
+++ b/config.ini
@@ -1,5 +1,5 @@
[rpc]
-status = 1 # 模式 0关闭 1服务端 2客户端
+status = 0 # 模式 0关闭 1服务端 2客户端
addr = 0.0.0.0:7879 # RPC 服务端地址 or 客户端地址
name = Server # 状态1 服务端 名称 状态2 客户端 名称
@@ -7,8 +7,9 @@ name = Server # 状态1 服务端 名称 状
addr = 0.0.0.0:9001 # 管理后台启动地址
account = admin # 登录账号
password = admin # 登录密码
-db_type = sqlite # 1 sqlite 2 mysql
-db_max_open = 5 # 最大连接池,0 表示无限制
+db_type = sqlite # sqlite or mysql
+db_max_open = 50 # 最大连接池,0 表示无限制
+db_max_idle = 50 # 最大空闲数,0 表示无限制
db_str = ./db/hfish.db?cache=shared&mode=rwc # sqlite or mysql 连接字符串
# sqlite : ./db/hfish.db?cache=shared&mode=rwc
# mysql : 账号:密码@tcp(地址:端口)/数据库名?charset=utf8&parseTime=true&loc=Local
@@ -54,7 +55,7 @@ addr = 0.0.0.0:3306 # Mysql 服务端地址 注意
files = /etc/passwd,/etc/group # Mysql 服务端读取客户端任意文件; 多写逗号分隔,会随机取
[telnet]
-status = 0 # 是否启动 Telnet 0 关闭 1 启动
+status = 1 # 是否启动 Telnet 0 关闭 1 启动
addr = 0.0.0.0:23 # Telnet 服务端地址 注意端口冲突
[ftp]
diff --git a/core/alert/alert.go b/core/alert/alert.go
index 00055e0..ed06416 100644
--- a/core/alert/alert.go
+++ b/core/alert/alert.go
@@ -13,9 +13,10 @@ import (
"HFish/view/data"
"github.com/gin-gonic/gin"
"HFish/error"
+ "sync"
)
-func AlertMail(model string, typex string, agent string, ipx string, country string, region string, city string, infox string) {
+func AlertMail(model string, typex string, agent string, ipx string, country string, region string, city string, infox string, wg *sync.WaitGroup) {
// 判断邮件通知
try.Try(func() {
// 只有新加入才会发送邮件通知
@@ -55,11 +56,14 @@ func AlertMail(model string, typex string, agent string, ipx string, country str
send.SendMail(config[4:], "[HFish]提醒你,"+typex+"有鱼上钩!", text, config)
}
}
+
+ wg.Done()
}).Catch(func() {
+ wg.Done()
})
}
-func AlertWebHook(id string, model string, typex string, projectName string, agent string, ipx string, country string, region string, city string, infox string, time string) {
+func AlertWebHook(id string, model string, typex string, projectName string, agent string, ipx string, country string, region string, city string, infox string, time string, wg *sync.WaitGroup) {
// 判断 WebHook 通知
try.Try(func() {
result, err := dbUtil.DB().Table("hfish_setting").Fields("status", "info").Where("type", "=", "webHook").First()
@@ -106,7 +110,10 @@ func AlertWebHook(id string, model string, typex string, projectName string, age
defer resp.Body.Close()
//defer request.Body.Close()
}
+
+ wg.Done()
}).Catch(func() {
+ wg.Done()
})
}
diff --git a/core/dbUtil/dbUtil.go b/core/dbUtil/dbUtil.go
index eb6e6fb..2562723 100644
--- a/core/dbUtil/dbUtil.go
+++ b/core/dbUtil/dbUtil.go
@@ -1,11 +1,11 @@
package dbUtil
import (
- "github.com/gohouse/gorose"
_ "github.com/go-sql-driver/mysql"
_ "github.com/mattn/go-sqlite3"
"HFish/utils/conf"
"HFish/utils/log"
+ "github.com/gohouse/gorose"
)
var engin *gorose.Engin
@@ -16,15 +16,16 @@ func init() {
dbType := conf.Get("admin", "db_type")
dbStr := conf.Get("admin", "db_str")
dbMaxOpen := conf.GetInt("admin", "db_max_open")
+ dbMaxIdle := conf.GetInt("admin", "db_max_idle")
if dbType == "sqlite" {
- engin, err = gorose.Open(&gorose.Config{Driver: "sqlite3", Dsn: dbStr, SetMaxOpenConns: dbMaxOpen})
+ engin, err = gorose.Open(&gorose.Config{Driver: "sqlite3", Dsn: dbStr, SetMaxOpenConns: dbMaxOpen, SetMaxIdleConns: dbMaxIdle})
if err != nil {
log.Pr("HFish", "127.0.0.1", "连接 Sqlite 数据库失败", err)
}
} else if dbType == "mysql" {
- engin, err = gorose.Open(&gorose.Config{Driver: "mysql", Dsn: dbStr, SetMaxOpenConns: dbMaxOpen})
+ engin, err = gorose.Open(&gorose.Config{Driver: "mysql", Dsn: dbStr, SetMaxOpenConns: dbMaxOpen, SetMaxIdleConns: dbMaxIdle})
if err != nil {
log.Pr("HFish", "127.0.0.1", "连接 Mysql 数据库失败", err)
diff --git a/core/pool/pool.go b/core/pool/pool.go
new file mode 100644
index 0000000..521e77f
--- /dev/null
+++ b/core/pool/pool.go
@@ -0,0 +1,12 @@
+package pool
+
+import (
+ "sync"
+ "github.com/panjf2000/ants"
+)
+
+func New(size int) (sync.WaitGroup, *ants.Pool) {
+ wg := sync.WaitGroup{}
+ pool, _ := ants.NewPool(size)
+ return wg, pool
+}
diff --git a/core/protocol/ftp/graval/commands.go b/core/protocol/ftp/graval/commands.go
index 4034c69..4a59d90 100644
--- a/core/protocol/ftp/graval/commands.go
+++ b/core/protocol/ftp/graval/commands.go
@@ -11,6 +11,9 @@ import (
"HFish/core/report"
"HFish/utils/is"
"HFish/core/rpc/client"
+ "sync"
+ "github.com/panjf2000/ants"
+ "HFish/core/pool"
)
type ftpCommand interface {
@@ -329,24 +332,42 @@ func (cmd commandPass) RequireAuth() bool {
return false
}
+// 加入线程池
+
+var (
+ wg sync.WaitGroup
+ poolX *ants.Pool
+)
+
+func init() {
+ wg, poolX = pool.New(10)
+ defer poolX.Release()
+}
+
func (cmd commandPass) Execute(conn *ftpConn, param string) {
- info := conn.reqUser + "&&" + param
- arr := strings.Split(conn.conn.RemoteAddr().String(), ":")
+ wg.Add(1)
+ poolX.Submit(func() {
- // 判断是否为 RPC 客户端
- if is.Rpc() {
- go client.ReportResult("FTP", "", arr[0], info, "0")
- } else {
- go report.ReportFTP(arr[0], "本机", info)
- }
+ info := conn.reqUser + "&&" + param
+ arr := strings.Split(conn.conn.RemoteAddr().String(), ":")
- if conn.driver.Authenticate(conn.reqUser, param) {
- conn.user = conn.reqUser
- conn.reqUser = ""
- conn.writeMessage(230, "Password ok, continue")
- } else {
- conn.writeMessage(530, "Incorrect password, not logged in")
- }
+ // 判断是否为 RPC 客户端
+ if is.Rpc() {
+ go client.ReportResult("FTP", "", arr[0], info, "0")
+ } else {
+ go report.ReportFTP(arr[0], "本机", info)
+ }
+
+ if conn.driver.Authenticate(conn.reqUser, param) {
+ conn.user = conn.reqUser
+ conn.reqUser = ""
+ conn.writeMessage(230, "Password ok, continue")
+ } else {
+ conn.writeMessage(530, "Incorrect password, not logged in")
+ }
+
+ wg.Done()
+ })
}
// commandPasv responds to the PASV FTP command.
diff --git a/core/protocol/memcache/memcache.go b/core/protocol/memcache/memcache.go
index 735f3e0..a2e4511 100644
--- a/core/protocol/memcache/memcache.go
+++ b/core/protocol/memcache/memcache.go
@@ -23,7 +23,6 @@ import (
"bufio"
"fmt"
"io"
- "log"
"net"
"os"
"strconv"
@@ -32,6 +31,8 @@ import (
"HFish/utils/is"
"HFish/core/rpc/client"
"HFish/core/report"
+ "HFish/core/pool"
+ "HFish/utils/log"
)
var linkedHashMap = LinkedHashMap.NewLinkedHashMap()
@@ -407,87 +408,91 @@ func tcpServer(address string, rateLimitChan chan int, exitChan chan int) {
exitChan <- 1
}
- log.Println("[Memcache TCP] Listning on " + address)
-
defer l.Close()
+ wg, poolX := pool.New(10)
+ defer poolX.Release()
+
for {
- conn, err := l.Accept()
- trackID := randNumber(100000, 999999)
+ wg.Add(1)
+ poolX.Submit(func() {
+ time.Sleep(time.Second * 2)
- if err != nil {
- fmt.Println(err.Error())
- continue
- }
+ conn, err := l.Accept()
- go func() {
- skip := false
- reader := bufio.NewReader(conn)
- log.Printf("[Memcache TCP %d] Accepted a client socket from %s\n", trackID, conn.RemoteAddr().String())
-
- arr := strings.Split(conn.RemoteAddr().String(), ":")
-
- // 判断是否为 RPC 客户端
- var id string
-
- if is.Rpc() {
- id = client.ReportResult("MEMCACHE", "", arr[0], conn.RemoteAddr().String()+" 已经连接", "0")
- } else {
- id = strconv.FormatInt(report.ReportMemCche(arr[0], "本机", conn.RemoteAddr().String()+" 已经连接"), 10)
+ if err != nil {
+ log.Pr("Mysql", "127.0.0.1", "Mysql 连接失败", err)
}
- for {
- <-rateLimitChan
- str, err := reader.ReadString('\n')
- if skip {
- skip = false
- continue
- }
- if err != nil {
- log.Printf("[Memcache TCP %d] Closed a client socket.\n", trackID)
- conn.Close()
- break
- }
- str = strings.TrimSpace(str)
+ go func() {
+ skip := false
+ reader := bufio.NewReader(conn)
+
+ arr := strings.Split(conn.RemoteAddr().String(), ":")
+
+ // 判断是否为 RPC 客户端
+ var id string
if is.Rpc() {
- go client.ReportResult("MEMCACHE", "", "", "&&"+str, id)
+ id = client.ReportResult("MEMCACHE", "", arr[0], conn.RemoteAddr().String()+" 已经连接", "0")
} else {
- go report.ReportUpdateMemCche(id, "&&"+str)
+ id = strconv.FormatInt(report.ReportMemCche(arr[0], "本机", conn.RemoteAddr().String()+" 已经连接"), 10)
}
- log.Printf("[Memcache TCP %d] Client request: %s.\n", trackID, str)
- args := strings.Split(str, " ")
- function, exist := commands[args[0]]
- if !exist {
- conn.Write(RESPONSE_ERROR)
- continue
- }
-
- args = args[1:]
-
for {
- response, requiredBytes := function(args)
- if requiredBytes == -1 {
+ <-rateLimitChan
+ str, err := reader.ReadString('\n')
+ if skip {
+ skip = false
+ continue
+ }
+ if err != nil {
conn.Close()
break
}
- if requiredBytes == 0 {
- conn.Write(response)
- break
+ str = strings.TrimSpace(str)
+
+ if is.Rpc() {
+ go client.ReportResult("MEMCACHE", "", "", "&&"+str, id)
+ } else {
+ go report.ReportUpdateMemCche(id, "&&"+str)
}
- data := make([]byte, requiredBytes)
- _, err = io.ReadFull(reader, data)
- if err != nil {
- break
+ args := strings.Split(str, " ")
+ function, exist := commands[args[0]]
+ if !exist {
+ conn.Write(RESPONSE_ERROR)
+ continue
}
- skip = true
- args = append(args, string(data))
+
+ args = args[1:]
+
+ for {
+ response, requiredBytes := function(args)
+ if requiredBytes == -1 {
+ conn.Close()
+ break
+ }
+ if requiredBytes == 0 {
+ conn.Write(response)
+ break
+ }
+
+ data := make([]byte, requiredBytes)
+ _, err = io.ReadFull(reader, data)
+ if err != nil {
+ break
+ }
+ skip = true
+ args = append(args, string(data))
+ }
+
}
- }
- }()
+ }()
+
+ wg.Done()
+ })
}
}
@@ -505,8 +510,6 @@ func udpServer(address string, rateLimitChan chan int, exitChan chan int) {
exitChan <- 1
}
- log.Println("[Memcache UDP] Listning on " + address)
-
go func() {
buf := make([]byte, 1500)
for {
@@ -523,7 +526,7 @@ func udpServer(address string, rateLimitChan chan int, exitChan chan int) {
if request == "" {
continue
}
- log.Printf("[Memcache UDP] Client request: [%s] from: %s\n", request, addr.String())
+
args := strings.Split(request, " ")
function, exist := commands[args[0]]
if !exist {
diff --git a/core/protocol/mysql/mysql.go b/core/protocol/mysql/mysql.go
index 334d950..ee64957 100644
--- a/core/protocol/mysql/mysql.go
+++ b/core/protocol/mysql/mysql.go
@@ -13,6 +13,8 @@ import (
"HFish/utils/is"
"HFish/core/rpc/client"
"strconv"
+ "HFish/core/pool"
+ "time"
)
//读取文件时每次读取的字节数
@@ -47,26 +49,38 @@ func Start(addr string, files string) {
// 读取文件列表
fileNames = strings.Split(files, ",")
+ wg, poolX := pool.New(10)
+ defer poolX.Release()
+
for {
- conn, _ := listener.Accept()
- ip, _, _ := net.SplitHostPort(conn.RemoteAddr().String())
+ wg.Add(1)
+ poolX.Submit(func() {
+ time.Sleep(time.Second * 2)
- //由于文件最后保存的文件名包含ip地址,为了本地测试加了这个
- if ip == "::1" {
- ip = "localhost"
- }
+ conn, err := listener.Accept()
- //这里记录每个客户端连接的次数,实现获取多个文件
- _, ok := recordClient[ip]
- if ok {
- if recordClient[ip] < len(fileNames)-1 {
- recordClient[ip] += 1
+ if err != nil {
+ log.Pr("Mysql", "127.0.0.1", "Mysql 连接失败", err)
}
- } else {
- recordClient[ip] = 0
- }
- go connectionClientHandler(conn)
+ arr := strings.Split(conn.RemoteAddr().String(), ":")
+
+ ip := arr[0]
+
+ //这里记录每个客户端连接的次数,实现获取多个文件
+ _, ok := recordClient[ip]
+ if ok {
+ if recordClient[ip] < len(fileNames)-1 {
+ recordClient[ip] += 1
+ }
+ } else {
+ recordClient[ip] = 0
+ }
+
+ go connectionClientHandler(conn)
+
+ wg.Done()
+ })
}
}
diff --git a/core/protocol/redis/redis.go b/core/protocol/redis/redis.go
index 0114cab..2056d39 100644
--- a/core/protocol/redis/redis.go
+++ b/core/protocol/redis/redis.go
@@ -11,6 +11,8 @@ import (
"HFish/utils/is"
"HFish/core/rpc/client"
"fmt"
+ "HFish/core/pool"
+ "time"
)
var kvData map[string]string
@@ -23,25 +25,37 @@ func Start(addr string) {
defer netListen.Close()
+ wg, poolX := pool.New(10)
+ defer poolX.Release()
+
for {
- conn, err := netListen.Accept()
- if err != nil {
- continue
- }
- arr := strings.Split(conn.RemoteAddr().String(), ":")
+ wg.Add(1)
+ poolX.Submit(func() {
+ time.Sleep(time.Second * 2)
- // 判断是否为 RPC 客户端
- var id string
+ conn, err := netListen.Accept()
- if is.Rpc() {
- id = client.ReportResult("REDIS", "", arr[0], conn.RemoteAddr().String()+" 已经连接", "0")
- } else {
- id = strconv.FormatInt(report.ReportRedis(arr[0], "本机", conn.RemoteAddr().String()+" 已经连接"), 10)
- }
+ if err != nil {
+ log.Pr("Redis", "127.0.0.1", "Redis 连接失败", err)
+ }
- log.Pr("Redis", arr[0], "已经连接")
+ arr := strings.Split(conn.RemoteAddr().String(), ":")
- go handleConnection(conn, id)
+ // 判断是否为 RPC 客户端
+ var id string
+
+ if is.Rpc() {
+ id = client.ReportResult("REDIS", "", arr[0], conn.RemoteAddr().String()+" 已经连接", "0")
+ } else {
+ id = strconv.FormatInt(report.ReportRedis(arr[0], "本机", conn.RemoteAddr().String()+" 已经连接"), 10)
+ }
+
+ log.Pr("Redis", arr[0], "已经连接")
+
+ go handleConnection(conn, id)
+
+ wg.Done()
+ })
}
}
diff --git a/core/protocol/telnet/telnet.go b/core/protocol/telnet/telnet.go
index d8056de..9276092 100644
--- a/core/protocol/telnet/telnet.go
+++ b/core/protocol/telnet/telnet.go
@@ -8,12 +8,14 @@ import (
"os"
"HFish/utils/is"
"HFish/core/rpc/client"
- "strconv"
"HFish/core/report"
"HFish/utils/log"
"github.com/bitly/go-simplejson"
"HFish/utils/json"
"HFish/utils/file"
+ "strconv"
+ "time"
+ "HFish/core/pool"
)
// 服务端连接
@@ -27,29 +29,38 @@ func server(address string, exitChan chan int) {
defer l.Close()
+ wg, poolX := pool.New(10)
+ defer poolX.Release()
+
for {
- conn, err := l.Accept()
+ wg.Add(1)
+ poolX.Submit(func() {
+ time.Sleep(time.Second * 2)
- if err != nil {
- fmt.Println(err.Error())
- continue
- }
+ conn, err := l.Accept()
- arr := strings.Split(conn.RemoteAddr().String(), ":")
+ if err != nil {
+ log.Pr("Telnet", "127.0.0.1", "Telnet 连接失败", err)
+ }
- // 判断是否为 RPC 客户端
- var id string
+ arr := strings.Split(conn.RemoteAddr().String(), ":")
- if is.Rpc() {
- id = client.ReportResult("TELNET", "", arr[0], conn.RemoteAddr().String()+" 已经连接", "0")
- } else {
- id = strconv.FormatInt(report.ReportTelnet(arr[0], "本机", conn.RemoteAddr().String()+" 已经连接"), 10)
- }
+ var id string
- log.Pr("Telnet", arr[0], "已经连接")
+ // 判断是否为 RPC 客户端
+ if is.Rpc() {
+ id = client.ReportResult("TELNET", "", arr[0], conn.RemoteAddr().String()+" 已经连接", "0")
+ } else {
+ id = strconv.FormatInt(report.ReportTelnet(arr[0], "本机", conn.RemoteAddr().String()+" 已经连接"), 10)
+ }
- // 根据连接开启会话, 这个过程需要并行执行
- go handleSession(conn, exitChan, id)
+ log.Pr("Telnet", arr[0], "已经连接")
+
+ // 根据连接开启会话, 这个过程需要并行执行
+ go handleSession(conn, exitChan, id)
+
+ wg.Done()
+ })
}
}
diff --git a/core/report/report.go b/core/report/report.go
index a3f2139..f637781 100644
--- a/core/report/report.go
+++ b/core/report/report.go
@@ -10,6 +10,9 @@ import (
"strings"
"HFish/core/alert"
"HFish/utils/conf"
+ "HFish/core/pool"
+ "sync"
+ "github.com/panjf2000/ants"
)
type HFishInfo struct {
@@ -26,16 +29,37 @@ type HFishInfo struct {
time string
}
+var (
+ wg sync.WaitGroup
+ poolX *ants.Pool
+
+ wgUpdate sync.WaitGroup
+ poolUpdateX *ants.Pool
+)
+
+func init() {
+ wg, poolX = pool.New(10)
+ defer poolX.Release()
+
+ wgUpdate, poolUpdateX = pool.New(10)
+ defer poolUpdateX.Release()
+}
+
// 通知模块
-func alertx(id string, model string, typex string, projectName string, agent string, ipx string, country string, region string, city string, infox string, time string) {
- // 邮件通知
- alert.AlertMail(model, typex, agent, ipx, country, region, city, infox)
+func alertx(id string, model string, typex string, projectName string, agent string, ipx string, country string, region string, city string, infox string, timex string) {
+ wg.Add(1)
+ poolX.Submit(func() {
+ time.Sleep(time.Second * 2)
- // WebHook
- alert.AlertWebHook(id, model, typex, projectName, agent, ipx, country, region, city, infox, time)
+ // 邮件通知
+ alert.AlertMail(model, typex, agent, ipx, country, region, city, infox, &wg)
- // 大数据展示
- //alert.AlertDataWs(model, typex, projectName, agent, ipx, country, region, city, time)
+ // WebHook
+ alert.AlertWebHook(id, model, typex, projectName, agent, ipx, country, region, city, infox, timex, &wg)
+
+ // 大数据展示
+ //alert.AlertDataWs(model, typex, projectName, agent, ipx, country, region, city, time)
+ })
}
// 上报 集群 状态
@@ -113,6 +137,7 @@ func isWhiteIp(ip string) bool {
// 通用的插入
func insertInfo(typex string, projectName string, agent string, ipx string, country string, region string, city string, info string) int64 {
+
id, err := dbUtil.DB().Table("hfish_info").Data(map[string]interface{}{
"type": typex,
"project_name": projectName,
@@ -128,38 +153,54 @@ func insertInfo(typex string, projectName string, agent string, ipx string, coun
if err != nil {
log.Pr("HFish", "127.0.0.1", "插入上钩信息失败", err)
}
+
return id
}
+// 更新
+func updateInfoCore(id string, info string) {
+ time.Sleep(time.Second * 2)
+
+ try.Try(func() {
+ var sql string
+
+ // 此处为了兼容 Mysql + Sqlite
+ dbType := conf.Get("admin", "db_type")
+
+ if dbType == "sqlite" {
+ sql = `
+ UPDATE hfish_info
+ SET info = info||?
+ WHERE
+ id = ?;
+ `
+ } else if dbType == "mysql" {
+ sql = `
+ UPDATE hfish_info
+ SET info = CONCAT(info, ?)
+ WHERE
+ id = ?;
+ `
+ }
+
+ _, err := dbUtil.DB().Execute(sql, info, id)
+
+ if err != nil {
+ log.Pr("HFish", "127.0.0.1", "更新上钩信息失败", err)
+ }
+
+ wgUpdate.Done()
+ }).Catch(func() {
+ wgUpdate.Done()
+ })
+}
+
// 通用的更新
func updateInfo(id string, info string) {
-
- var sql string
-
- // 此处为了兼容 Mysql + Sqlite
- dbType := conf.Get("admin", "db_type")
-
- if dbType == "sqlite" {
- sql = `
- UPDATE hfish_info
- SET info = info||?
- WHERE
- id = ?;
- `
- } else if dbType == "mysql" {
- sql = `
- UPDATE hfish_info
- SET info = CONCAT(info, ?)
- WHERE
- id = ?;
- `
- }
-
- _, err := dbUtil.DB().Execute(sql, info, id)
-
- if err != nil {
- log.Pr("HFish", "127.0.0.1", "更新上钩信息失败", err)
- }
+ wgUpdate.Add(1)
+ poolUpdateX.Submit(func() {
+ updateInfoCore(id, info)
+ })
}
// 上报 WEB
@@ -194,6 +235,12 @@ func ReportPlugWeb(projectName string, agent string, ipx string, info string) {
// 上报 SSH
func ReportSSH(ipx string, agent string, info string) int64 {
+ defer func() {
+ if err := recover(); err != nil {
+ log.Pr("HFish", "127.0.0.1", "执行SSH插入失败", err)
+ }
+ }()
+
// IP 不在白名单,进行上报
if (isWhiteIp(ipx) == false) {
country, region, city := ip.GetIp(ipx)
@@ -206,6 +253,12 @@ func ReportSSH(ipx string, agent string, info string) int64 {
// 更新 SSH 操作
func ReportUpdateSSH(id string, info string) {
+ defer func() {
+ if err := recover(); err != nil {
+ log.Pr("HFish", "127.0.0.1", "执行SSH更新失败", err)
+ }
+ }()
+
if (id != "0") {
go updateInfo(id, info)
go alertx(id, "update", "SSH", "SSH蜜罐", "", "", "", "", "", info, time.Now().Format("2006-01-02 15:04:05"))
diff --git a/db/hfish.db b/db/hfish.db
index 358601c..510e0e2 100644
Binary files a/db/hfish.db and b/db/hfish.db differ
diff --git a/db/sql/hfish_colony.sql b/db/sql/hfish_colony.sql
new file mode 100644
index 0000000..4a081a6
--- /dev/null
+++ b/db/sql/hfish_colony.sql
@@ -0,0 +1,24 @@
+-- ----------------------------
+-- Table structure for `hfish_colony`
+-- ----------------------------
+DROP TABLE IF EXISTS `hfish_colony`;
+CREATE TABLE `hfish_colony` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `agent_name` varchar(20) NOT NULL DEFAULT '',
+ `agent_ip` varchar(20) NOT NULL DEFAULT '',
+ `web_status` int(2) NOT NULL DEFAULT '0',
+ `deep_status` int(2) NOT NULL DEFAULT '0',
+ `ssh_status` int(2) NOT NULL DEFAULT '0',
+ `redis_status` int(2) NOT NULL DEFAULT '0',
+ `mysql_status` int(2) NOT NULL DEFAULT '0',
+ `http_status` int(2) NOT NULL DEFAULT '0',
+ `telnet_status` int(2) NOT NULL DEFAULT '0',
+ `ftp_status` int(2) NOT NULL DEFAULT '0',
+ `mem_cache_status` int(2) NOT NULL DEFAULT '0',
+ `plug_status` int(2) NOT NULL DEFAULT '0',
+ `last_update_time` datetime NOT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `un_agent` (`agent_name`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
+
+SET FOREIGN_KEY_CHECKS = 1;
diff --git a/db/sql/hfish_info.sql b/db/sql/hfish_info.sql
new file mode 100644
index 0000000..8af17f6
--- /dev/null
+++ b/db/sql/hfish_info.sql
@@ -0,0 +1,19 @@
+-- ----------------------------
+-- Table structure for `hfish_info`
+-- ----------------------------
+DROP TABLE IF EXISTS `hfish_info`;
+CREATE TABLE `hfish_info` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `type` varchar(20) NOT NULL DEFAULT '',
+ `project_name` varchar(20) NOT NULL DEFAULT '',
+ `agent` varchar(20) NOT NULL DEFAULT '',
+ `ip` varchar(20) NOT NULL DEFAULT '',
+ `country` varchar(10) NOT NULL DEFAULT '',
+ `region` varchar(10) NOT NULL DEFAULT '',
+ `city` varchar(10) NOT NULL,
+ `info` text NOT NULL,
+ `create_time` datetime NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
+
+SET FOREIGN_KEY_CHECKS = 1;
diff --git a/db/sql/hfish_setting.sql b/db/sql/hfish_setting.sql
new file mode 100644
index 0000000..daac760
--- /dev/null
+++ b/db/sql/hfish_setting.sql
@@ -0,0 +1,24 @@
+-- ----------------------------
+-- Table structure for `hfish_setting`
+-- ----------------------------
+DROP TABLE IF EXISTS `hfish_setting`;
+CREATE TABLE `hfish_setting` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `type` varchar(50) NOT NULL DEFAULT '',
+ `info` varchar(50) NOT NULL DEFAULT '',
+ `update_time` datetime NOT NULL,
+ `status` int(2) NOT NULL DEFAULT '0',
+ `setting_name` varchar(50) NOT NULL DEFAULT '',
+ `setting_dis` varchar(50) NOT NULL DEFAULT '',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `index_key` (`type`)
+) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;
+
+-- ----------------------------
+-- Records of `hfish_setting`
+-- ----------------------------
+BEGIN;
+INSERT INTO `hfish_setting` VALUES ('1', 'mail', '', '2019-09-02 20:15:00', '0', 'E-mail 群发', '群发邮件SMTP服务器配置'), ('2', 'alertMail', '', '2019-09-02 18:58:12', '0', 'E-mail 通知', '蜜罐告警会通过邮件告知信息'), ('3', 'webHook', '', '2019-09-03 11:49:00', '0', 'WebHook 通知', '蜜罐告警会请求指定API告知信息'), ('4', 'whiteIp', '', '2019-09-02 20:15:00', '0', 'IP 白名单', '蜜罐上钩会过滤掉白名单IP');
+COMMIT;
+
+SET FOREIGN_KEY_CHECKS = 1;
diff --git a/error/error.go b/error/error.go
index d65d8a2..8f07b54 100644
--- a/error/error.go
+++ b/error/error.go
@@ -19,6 +19,9 @@ const (
ErrFailConfigCode = 1004
ErrFailConfigMsg = "请配置后在启用"
+
+ ErrFailPlugCode = 1005
+ ErrFailPlugMsg = "上报信息错误"
)
func Check(e error, tips string) {
diff --git a/go.mod b/go.mod
index 6767413..101278d 100644
--- a/go.mod
+++ b/go.mod
@@ -12,13 +12,17 @@ require (
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
github.com/gin-gonic/gin v1.4.0
github.com/gliderlabs/ssh v0.2.2
- github.com/gorilla/websocket v1.4.1 // indirect
+ github.com/go-sql-driver/mysql v1.4.1
+ github.com/gohouse/gorose v0.0.0-20190830103550-ad3ce0985b9e
+ github.com/gorilla/websocket v1.4.1
github.com/ipipdotnet/ipdb-go v1.2.0
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869
github.com/kr/pretty v0.1.0 // indirect
github.com/mattn/go-sqlite3 v1.11.0
+ github.com/panjf2000/ants v1.2.0
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect
- golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
+ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5
+ google.golang.org/appengine v1.6.2 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/ini.v1 v1.46.0
diff --git a/go.sum b/go.sum
index bc1e801..b8144b4 100644
--- a/go.sum
+++ b/go.sum
@@ -20,6 +20,14 @@ github.com/gin-gonic/gin v1.4.0 h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ=
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
+github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
+github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
+github.com/gohouse/gocar v0.0.2 h1:pzf7zhDSuWa7GpSszi6mEQslp+Pthypn5yi8c+zomK0=
+github.com/gohouse/gocar v0.0.2/go.mod h1:zE2+ip1u8MKvLyqTKxQIeZEI4lN1XPXK7AZdbikD6RE=
+github.com/gohouse/gorose v0.0.0-20190830103550-ad3ce0985b9e h1:gvQbXcpfZzyVnUOUDYdy2TRm0z8WATHgHQ+CJZYjFSE=
+github.com/gohouse/gorose v0.0.0-20190830103550-ad3ce0985b9e/go.mod h1:+1d8SYnSZQxO01R1Vj65tKQ873DN6hHgVtJ9CmGPpQ0=
+github.com/gohouse/t v0.0.5 h1:ol19APh/fC7usS2XgZ7i3Usgo8eF9xszOPfGPhR6Zg8=
+github.com/gohouse/t v0.0.5/go.mod h1:CUtvHWNU9GY0Lvk+gcrhs9Ixmei7J5QQXiAvqcwccsk=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
@@ -41,12 +49,15 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/panjf2000/ants v1.2.0 h1:Ufw4aDz9RqH1RVblx2W9L9Uv5vSX5apbX5+peR7LQ5k=
+github.com/panjf2000/ants v1.2.0/go.mod h1:AaACblRPzq35m1g3enqYcxspbbiOJJYaxU2wMpm1cXY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
@@ -61,15 +72,29 @@ github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65 h1:+rhAzEzT3f4JtomfC371qB+0Ola2caSKcY69NUBZrRQ=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c h1:+EXw7AwNOKzPFXMZ1yNjO40aWCh3PIquJB2fYlv9wcs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+google.golang.org/appengine v1.6.2 h1:j8RI1yW0SkI+paT6uGwMlrMI/6zwYA6/CFil8rxOzGI=
+google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
diff --git a/main.go b/main.go
index b3c60be..88f302c 100644
--- a/main.go
+++ b/main.go
@@ -17,7 +17,7 @@ func main() {
} else if args[1] == "init" || args[1] == "--init" {
setting.Init()
} else if args[1] == "version" || args[1] == "--version" {
- fmt.Println("v0.3")
+ fmt.Println("v0.3.1")
} else if args[1] == "run" || args[1] == "--run" {
setting.Run()
} else {
diff --git a/view/api/view.go b/view/api/view.go
index 488c110..32138aa 100644
--- a/view/api/view.go
+++ b/view/api/view.go
@@ -10,6 +10,7 @@ import (
"HFish/core/rpc/client"
"HFish/utils/is"
"HFish/utils/log"
+ "fmt"
)
// 上报WEB蜜罐
@@ -30,6 +31,8 @@ func ReportWeb(c *gin.Context) {
"code": error.ErrFailApiKeyCode,
"msg": error.ErrFailApiKeyMsg,
})
+
+ return
} else {
// 判断是否为 RPC 客户端
@@ -64,6 +67,8 @@ func ReportDeepWeb(c *gin.Context) {
"code": error.ErrFailApiKeyCode,
"msg": error.ErrFailApiKeyMsg,
})
+
+ return
} else {
// 判断是否为 RPC 客户端
@@ -80,26 +85,60 @@ func ReportDeepWeb(c *gin.Context) {
}
}
+type PlugInfo struct {
+ Name string `json:"name"`
+ Ip string `json:"ip"`
+ SecKey string `json:"sec_key"`
+ Info map[string]interface{} `json:"info"`
+}
+
// 蜜罐插件API
func ReportPlugWeb(c *gin.Context) {
- name := c.PostForm("name")
- info := c.PostForm("info")
- secKey := c.PostForm("sec_key")
- ip := c.PostForm("ip")
+ var info PlugInfo
+ err := c.BindJSON(&info)
+
+ if err != nil {
+ fmt.Println(err)
+ log.Pr("HFish", "127.0.0.1", "插件上报信息错误", err)
+
+ c.JSON(http.StatusOK, gin.H{
+ "code": error.ErrFailPlugCode,
+ "msg": error.ErrFailPlugMsg,
+ "data": err,
+ })
+ return
+ }
+
+ args := ""
+
+ if len(info.Info) != 0 {
+ for k, v := range info.Info["args"].(map[string]interface{}) {
+ if args == "" {
+ args += k + "=" + v.(string)
+ } else {
+ args += "&" + k + "=" + v.(string)
+ }
+ }
+ }
+
+ data := "Host:" + info.Info["host"].(string) + "&&Url:" + info.Info["uri"].(string) + "&&Method:" + info.Info["method"].(string) + "&&Args:" + args + "&&UserAgent:" + info.Info["http_user_agent"].(string) + "&&RemoteAddr:" + info.Info["remote_addr"].(string) + "&&TimeLocal:" + info.Info["time_local"].(string)
apiSecKey := conf.Get("api", "sec_key")
- if secKey != apiSecKey {
+ if info.SecKey != apiSecKey {
c.JSON(http.StatusOK, gin.H{
"code": error.ErrFailApiKeyCode,
"msg": error.ErrFailApiKeyMsg,
})
+
+ return
} else {
+
// 判断是否为 RPC 客户端
if is.Rpc() {
- go client.ReportResult("PLUG", name, ip, info, "0")
+ go client.ReportResult("PLUG", info.Name, info.Ip, data, "0")
} else {
- go report.ReportPlugWeb(name, "本机", ip, info)
+ go report.ReportPlugWeb(info.Name, "本机", info.Ip, data)
}
c.JSON(http.StatusOK, gin.H{
|