mirror of
https://github.com/Li4n0/revsuit.git
synced 2026-09-21 22:30:46 +08:00
feat: complete basic functions
Support http,dns and mysql connection. Support custom http, dns response. Support dns rebinding. Support mysql load local files and jdbc deserialize exploit.
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/li4n0/revsuit/pkg/dns"
|
||||
"github.com/li4n0/revsuit/pkg/mysql"
|
||||
"github.com/li4n0/revsuit/pkg/rhttp"
|
||||
)
|
||||
|
||||
type noticeConfig struct {
|
||||
DingTalk string
|
||||
Lark string
|
||||
WeiXin string
|
||||
Slack string
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Addr string
|
||||
Token string
|
||||
Database string
|
||||
LogLevel string
|
||||
Notice noticeConfig
|
||||
rhttp.Config
|
||||
DNS dns.Config
|
||||
Mysql mysql.Config
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/li4n0/revsuit/internal/record"
|
||||
log "unknwon.dev/clog/v2"
|
||||
)
|
||||
|
||||
func ping(c *gin.Context) {
|
||||
c.SetCookie("token", c.Request.Header["Token"][0], 0, "/revsuit/api/", c.Request.Host, true, true)
|
||||
c.String(200, "pong")
|
||||
}
|
||||
|
||||
func events(c *gin.Context) {
|
||||
log.Info("Receive connection from ", c.Request.RemoteAddr)
|
||||
c.Stream(func(w io.Writer) bool {
|
||||
c.SSEvent("message", "connect succeed")
|
||||
select {
|
||||
case <-c.Writer.CloseNotify():
|
||||
return false
|
||||
case r := <-record.Channel():
|
||||
c.SSEvent("message", r.GetFlag())
|
||||
}
|
||||
return true
|
||||
})
|
||||
log.Info(c.Request.RemoteAddr, "disconnect")
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/li4n0/revsuit/frontend"
|
||||
"github.com/li4n0/revsuit/pkg/dns"
|
||||
"github.com/li4n0/revsuit/pkg/mysql"
|
||||
"github.com/li4n0/revsuit/pkg/rhttp"
|
||||
log "unknwon.dev/clog/v2"
|
||||
)
|
||||
|
||||
func (revsuit *Revsuit) registerRouter() {
|
||||
revsuit.http.Router = gin.Default()
|
||||
revsuit.registerPlatformRouter()
|
||||
revsuit.registerHttpRouter()
|
||||
}
|
||||
|
||||
func (revsuit *Revsuit) registerPlatformRouter() {
|
||||
// /api need Authorization
|
||||
api := revsuit.http.Router.Group("/revsuit/api")
|
||||
api.Use(func(c *gin.Context) {
|
||||
cookieToken, err := c.Request.Cookie("token")
|
||||
if !(c.Request.Header.Get("Token") == revsuit.http.Token || err == nil && cookieToken.Value == revsuit.http.Token) {
|
||||
c.Abort()
|
||||
c.Status(403)
|
||||
return
|
||||
}
|
||||
})
|
||||
revsuit.http.ApiGroup = api
|
||||
|
||||
//platform routers
|
||||
api.GET("/events", events)
|
||||
api.GET("/ping", ping)
|
||||
}
|
||||
|
||||
func (revsuit *Revsuit) registerHttpRouter() {
|
||||
revsuit.http.Router.NoRoute(revsuit.http.Receive)
|
||||
|
||||
//register frontend
|
||||
fe, err := fs.Sub(frontend.FS, "dist")
|
||||
if err != nil {
|
||||
log.Fatal("Failed to sub path `dist`: %v", err)
|
||||
}
|
||||
revsuit.http.Router.StaticFS("/revsuit/admin", http.FS(fe))
|
||||
|
||||
// init record router group
|
||||
recordGroup := revsuit.http.ApiGroup.Group("/record")
|
||||
|
||||
httpGroup := recordGroup.Group("/http")
|
||||
httpGroup.GET("", rhttp.ListRecords)
|
||||
|
||||
dnsGroup := recordGroup.Group("/dns")
|
||||
dnsGroup.GET("", dns.List)
|
||||
|
||||
mysqlGroup := recordGroup.Group("/mysql")
|
||||
mysqlGroup.GET("", mysql.List)
|
||||
|
||||
// init rule router group
|
||||
ruleGroup := revsuit.http.ApiGroup.Group("/rule")
|
||||
|
||||
httpGroup = ruleGroup.Group("/http")
|
||||
httpGroup.GET("", rhttp.ListRules)
|
||||
httpGroup.POST("", rhttp.UpsertRules)
|
||||
httpGroup.DELETE("", rhttp.DeleteRules)
|
||||
|
||||
dnsGroup = ruleGroup.Group("/dns")
|
||||
dnsGroup.GET("", dns.ListRules)
|
||||
dnsGroup.POST("", dns.UpsertRules)
|
||||
dnsGroup.DELETE("", dns.DeleteRules)
|
||||
|
||||
mysqlGroup = ruleGroup.Group("/mysql")
|
||||
mysqlGroup.GET("", mysql.ListRules)
|
||||
mysqlGroup.POST("", mysql.UpsertRules)
|
||||
mysqlGroup.DELETE("", mysql.DeleteRules)
|
||||
|
||||
// init file router group
|
||||
fileGroup := revsuit.http.ApiGroup.Group("/file")
|
||||
fileGroup.GET("/mysql/:id", mysql.GetFile)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/li4n0/revsuit/internal/database"
|
||||
"github.com/li4n0/revsuit/internal/notice"
|
||||
"github.com/li4n0/revsuit/pkg/dns"
|
||||
"github.com/li4n0/revsuit/pkg/mysql"
|
||||
http "github.com/li4n0/revsuit/pkg/rhttp"
|
||||
"gorm.io/gorm/logger"
|
||||
log "unknwon.dev/clog/v2"
|
||||
)
|
||||
|
||||
type Revsuit struct {
|
||||
http *http.Server
|
||||
dns *dns.Server
|
||||
mysql *mysql.Server
|
||||
}
|
||||
|
||||
func initDatabase(dsn string) {
|
||||
err := database.InitDB("sqlite", dsn)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
err = database.DB.AutoMigrate(&http.Record{})
|
||||
err = database.DB.AutoMigrate(&dns.Record{})
|
||||
err = database.DB.AutoMigrate(&mysql.Record{})
|
||||
err = database.DB.AutoMigrate(&http.Rule{})
|
||||
err = database.DB.AutoMigrate(&dns.Rule{})
|
||||
err = database.DB.AutoMigrate(&mysql.Rule{})
|
||||
err = database.DB.AutoMigrate(&mysql.File{})
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func initLog(level string) {
|
||||
var logLevel log.Level
|
||||
|
||||
switch level {
|
||||
case "debug":
|
||||
gin.SetMode(gin.DebugMode)
|
||||
database.DB.Logger.LogMode(logger.Info)
|
||||
logLevel = log.LevelTrace
|
||||
case "info":
|
||||
gin.SetMode(gin.DebugMode)
|
||||
database.DB.Logger.LogMode(logger.Info)
|
||||
logLevel = log.LevelInfo
|
||||
case "warning":
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
database.DB.Logger.LogMode(logger.Warn)
|
||||
logLevel = log.LevelWarn
|
||||
case "error":
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
database.DB.Logger.LogMode(logger.Error)
|
||||
logLevel = log.LevelError
|
||||
case "fatal":
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
database.DB.Logger.LogMode(logger.Error)
|
||||
logLevel = log.LevelFatal
|
||||
}
|
||||
_ = log.NewConsole(100,
|
||||
log.ConsoleConfig{
|
||||
Level: logLevel,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func initNotice(nc noticeConfig) {
|
||||
n := notice.New()
|
||||
if nc.DingTalk != "" {
|
||||
n.AddBot(¬ice.DingTalk{
|
||||
URL: nc.DingTalk,
|
||||
})
|
||||
}
|
||||
if nc.Lark != "" {
|
||||
n.AddBot(¬ice.Lark{
|
||||
URL: nc.Lark,
|
||||
})
|
||||
}
|
||||
if nc.WeiXin != "" {
|
||||
n.AddBot(¬ice.Weixin{
|
||||
URL: nc.WeiXin,
|
||||
})
|
||||
}
|
||||
if nc.Slack != "" {
|
||||
n.AddBot(¬ice.Slack{
|
||||
URL: nc.Slack,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func New(c *Config) *Revsuit {
|
||||
|
||||
initDatabase(c.Database)
|
||||
initLog(c.LogLevel)
|
||||
initNotice(c.Notice)
|
||||
|
||||
s := &Revsuit{
|
||||
http: http.GetServer(),
|
||||
}
|
||||
if c.DNS.Enable {
|
||||
s.dns = dns.GetServer()
|
||||
}
|
||||
if c.Mysql.Enable {
|
||||
s.mysql = mysql.GetServer()
|
||||
s.mysql.Config = c.Mysql
|
||||
}
|
||||
|
||||
if c.Addr != "" {
|
||||
s.http.SetAddr(c.Addr)
|
||||
}
|
||||
if c.Token != "" {
|
||||
s.http.SetToken(c.Token)
|
||||
}
|
||||
if c.IpHeader != "" {
|
||||
s.http.SetIpHeader(c.IpHeader)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (revsuit *Revsuit) Run() {
|
||||
defer log.Stop()
|
||||
revsuit.registerRouter()
|
||||
|
||||
if revsuit.dns != nil {
|
||||
go revsuit.dns.Run()
|
||||
}
|
||||
if revsuit.mysql != nil {
|
||||
go revsuit.mysql.Run()
|
||||
}
|
||||
|
||||
revsuit.http.Run()
|
||||
}
|
||||
Reference in New Issue
Block a user