release 0.1.3-beta (#19)

Co-authored-by: E99p1ant <[email protected]>
This commit is contained in:
Li4n0
2021-05-25 20:41:37 +08:00
committed by GitHub
co-authored by E99p1ant
parent 1144f67d37
commit cbbf3ba0ba
68 changed files with 640 additions and 197 deletions
+2 -2
View File
@@ -53,7 +53,7 @@ func (s *Server) getRules() []*Rule {
return s.rules
}
func (s *Server) updateRules() error {
func (s *Server) UpdateRules() error {
db := database.DB.Model(new(Rule))
defer s.rulesLock.Unlock()
s.rulesLock.Lock()
@@ -209,7 +209,7 @@ func (s *Server) Run() {
s.livingLock.Unlock()
}()
if err := s.updateRules(); err != nil {
if err := s.UpdateRules(); err != nil {
log.Error(err.Error())
return
}
+2 -2
View File
@@ -58,7 +58,7 @@ func (r *Rule) CreateOrUpdate() (err error) {
if err != nil {
return
}
err = GetServer().updateRules()
err = GetServer().UpdateRules()
return err
}
@@ -69,7 +69,7 @@ func (r *Rule) Delete() (err error) {
if err != nil {
return
}
err = GetServer().updateRules()
err = GetServer().UpdateRules()
return err
}
+5 -6
View File
@@ -67,7 +67,7 @@ func (s *Server) getRules() []*Rule {
return s.rules
}
func (s *Server) updateRules() error {
func (s *Server) UpdateRules() error {
db := database.DB.Model(new(Rule))
defer s.rulesLock.Unlock()
s.rulesLock.Lock()
@@ -94,6 +94,7 @@ func (s *Server) authenticate(user, password string) (_rule *Rule, flag, flagGro
}
func (s *Server) getPasvAddressFromCache(ip, pasvAddressTpl string) (pasvAddress string) {
pasvAddress = pasvAddressTpl
if strings.Contains(pasvAddressTpl, ",") {
values, ok := rebindingCache.Get(ip)
if !ok {
@@ -202,8 +203,8 @@ loop:
if pasvAddress = s.getPasvAddressFromCache(ip, _rule.PasvAddress); pasvAddress == "" {
pasvAddress = fmt.Sprintf("%s:%d", s.pasvIP, s.PasvPort)
}
isRedirect = rule.CompileTpl(pasvAddress, vars) != fmt.Sprintf("%s:%d", s.pasvIP, s.PasvPort)
pasvAddress = rule.CompileTpl(pasvAddress, vars)
isRedirect = pasvAddress != fmt.Sprintf("%s:%d", s.pasvIP, s.PasvPort)
case "SIZE":
path += strings.TrimLeft(args, "/")
if _rule == nil || isRedirect || len(_rule.Data) == 0 {
@@ -217,8 +218,6 @@ loop:
case "PASV":
//Just so that ide does not prompt that there may be a nil value
if _rule != nil {
// return rule's pasv_address or default pasv address
pasvAddress := rule.CompileTpl(pasvAddress, vars)
pasvIP, pasvPort, err := net.SplitHostPort(pasvAddress)
if err != nil {
log.Warn("FTP failed to split rule[id:%d] pasv_address(%s) :%s", _rule.ID, pasvAddress, err)
@@ -365,7 +364,7 @@ func (s *Server) Run() {
s.livingLock.Unlock()
}()
if err := s.updateRules(); err != nil {
if err := s.UpdateRules(); err != nil {
log.Error(err.Error())
return
}
+2 -2
View File
@@ -54,7 +54,7 @@ func (r *Rule) CreateOrUpdate() (err error) {
return
}
return GetServer().updateRules()
return GetServer().UpdateRules()
}
// Delete deletes the ftp rule in database and ruleSet
@@ -65,7 +65,7 @@ func (r *Rule) Delete() (err error) {
return
}
return GetServer().updateRules()
return GetServer().UpdateRules()
}
// ListRules lists all ftp rules those satisfy the filter
+4 -4
View File
@@ -48,7 +48,7 @@ func (s *Server) getRules() []*Rule {
return s.rules
}
func (s *Server) updateRules() error {
func (s *Server) UpdateRules() error {
db := database.DB.Model(new(Rule))
defer s.rulesLock.Unlock()
s.rulesLock.Lock()
@@ -105,11 +105,11 @@ func (s *Server) ConnectionClosed(c *vmysql.Conn) {
var clientName, clientOS, flag, flagGroup string
user := c.User
schema := c.SchemaName
supportLoadLocalData := c.SupportLoadDataLocal
cr, ok := s.connRulePool.Load(c.ConnectionID)
if !ok {
log.Warn("MySQL Connection rule(%d) not match flag", c.ConnectionID)
return
}
@@ -130,7 +130,7 @@ func (s *Server) ConnectionClosed(c *vmysql.Conn) {
}
}
r, err := newRecord(_rule, flag, user, clientName, clientOS, ip, qqwry.Area(ip), supportLoadLocalData, files)
r, err := newRecord(_rule, flag, user, schema, clientName, clientOS, ip, qqwry.Area(ip), supportLoadLocalData, files)
if err != nil {
log.Warn("MySQL record[rule_id: %s] created failed: %s", _rule.Name, err)
return
@@ -288,7 +288,7 @@ func (s *Server) Run() {
s.Enable = false
s.livingLock.Unlock()
}()
if err := s.updateRules(); err != nil {
if err := s.UpdateRules(); err != nil {
log.Error(err.Error())
return
}
+6 -1
View File
@@ -17,6 +17,7 @@ type Record struct {
record.BaseRecord
Username string `gorm:"index" form:"username" json:"username" notice:"username"`
ClientName string `gorm:"index" form:"client_name" json:"client_name" notice:"client_name"`
Schema string `gorm:"index" form:"schema" json:"schema" notice:"schema"`
ClientOS string `gorm:"index" form:"client_os" json:"client_os" notice:"client_os"`
LoadLocalData bool `gorm:"index" form:"load_local_data" json:"load_local_data" notice:"load_local_data"`
Files []file.MySQLFile `form:"-" json:"files" notice:"-"`
@@ -31,7 +32,7 @@ func (r Record) Notice() {
notice.Notice(r)
}
func newRecord(rule *Rule, flag, username, clientName, clientOS, remoteIp, ipArea string, supportLoadLocalData bool, files []file.MySQLFile) (r *Record, err error) {
func newRecord(rule *Rule, flag, username, schema, clientName, clientOS, remoteIp, ipArea string, supportLoadLocalData bool, files []file.MySQLFile) (r *Record, err error) {
r = &Record{
BaseRecord: record.BaseRecord{
Flag: flag,
@@ -40,6 +41,7 @@ func newRecord(rule *Rule, flag, username, clientName, clientOS, remoteIp, ipAre
RequestTime: time.Now(),
},
Username: username,
Schema: schema,
ClientName: clientName,
ClientOS: clientOS,
LoadLocalData: supportLoadLocalData,
@@ -90,6 +92,9 @@ func ListRecords(c *gin.Context) {
if mysqlRecord.ClientName != "" {
db.Where("client_name like ?", "%"+mysqlRecord.ClientName)
}
if mysqlRecord.Schema != "" {
db.Where("schema like ?", "%"+mysqlRecord.Schema)
}
if c.Query("load_local_data") != "" {
if c.Query("load_local_data") == "true" {
db.Where("load_local_data = ?", true)
+2 -2
View File
@@ -41,7 +41,7 @@ func (r *Rule) CreateOrUpdate() (err error) {
if err != nil {
return
}
err = GetServer().updateRules()
err = GetServer().UpdateRules()
return err
}
@@ -52,7 +52,7 @@ func (r *Rule) Delete() (err error) {
if err != nil {
return
}
err = GetServer().updateRules()
err = GetServer().UpdateRules()
return err
}
+7 -8
View File
@@ -83,7 +83,7 @@ func (s *Server) getRules() []*Rule {
return s.rules
}
func (s *Server) updateRules() error {
func (s *Server) UpdateRules() error {
db := database.DB.Model(new(Rule))
defer s.rulesLock.Unlock()
s.rulesLock.Lock()
@@ -116,7 +116,7 @@ func (s *Server) Restart() {
}
func (s *Server) Run() {
if err := s.updateRules(); err != nil {
if err := s.UpdateRules(); err != nil {
log.Warn(err.Error())
}
for {
@@ -156,8 +156,12 @@ func compileTpl(c *gin.Context, tpl string, vars map[string]string) (compiled st
func (s *Server) Receive(c *gin.Context) {
u := c.Request.URL.String()
raw, err := getRawRequest(c.Request)
if err != nil {
log.Warn(err.Error())
}
for _, _rule := range s.getRules() {
flag, flagGroup, vars := _rule.Match(u)
flag, flagGroup, vars := _rule.Match(string(raw))
if flag == "" {
continue
}
@@ -172,11 +176,6 @@ func (s *Server) Receive(c *gin.Context) {
delete(c.Request.Header, s.IpHeader)
}
raw, err := getRawRequest(c.Request)
if err != nil {
log.Warn(err.Error())
}
// create new record
r, err := NewRecord(_rule, flag, c.Request.Method, u, ip, area, string(raw))
if err != nil {
+4 -4
View File
@@ -14,7 +14,7 @@ var _ record.Record = (*Record)(nil)
type Record struct {
Method string `gorm:"index" form:"method" json:"method"`
Path string `form:"path" json:"path"`
URI string `form:"uri" json:"uri"`
record.BaseRecord
RawRequest string `json:"raw_request" notice:"-"`
Rule Rule `gorm:"foreignKey:RuleName;references:Name;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;" form:"-" json:"-" notice:"-"`
@@ -37,7 +37,7 @@ func NewRecord(rule *Rule, flag, method, url, ip, area, raw string) (r *Record,
RequestTime: time.Now(),
},
Method: method,
Path: url,
URI: url,
RawRequest: raw,
Rule: *rule,
}
@@ -78,8 +78,8 @@ func ListRecords(c *gin.Context) {
if httpRecord.Method != "" {
db.Where("method = ?", httpRecord.Method)
}
if httpRecord.Path != "" {
db.Where("path like ?", "%"+httpRecord.Path+"%")
if httpRecord.URI != "" {
db.Where("path like ?", "%"+httpRecord.URI+"%")
}
if httpRecord.RemoteIP != "" {
db.Where("remote_ip = ?", httpRecord.RemoteIP)
+2 -2
View File
@@ -58,7 +58,7 @@ func (r *Rule) CreateOrUpdate() (err error) {
return
}
err = GetServer().updateRules()
err = GetServer().UpdateRules()
return err
}
@@ -70,7 +70,7 @@ func (r *Rule) Delete() (err error) {
return
}
err = GetServer().updateRules()
err = GetServer().UpdateRules()
return err
}
+2 -2
View File
@@ -41,7 +41,7 @@ func (s *Server) getRules() []*Rule {
return s.rules
}
func (s *Server) updateRules() error {
func (s *Server) UpdateRules() error {
db := database.DB.Model(new(Rule))
defer s.rulesLock.Unlock()
s.rulesLock.Lock()
@@ -165,7 +165,7 @@ func (s *Server) Run() {
s.livingLock.Unlock()
}()
if err := s.updateRules(); err != nil {
if err := s.UpdateRules(); err != nil {
log.Error(err.Error())
return
}
+2 -2
View File
@@ -49,7 +49,7 @@ func (r *Rule) CreateOrUpdate() (err error) {
return
}
err = GetServer().updateRules()
err = GetServer().UpdateRules()
return err
}
@@ -61,7 +61,7 @@ func (r *Rule) Delete() (err error) {
return
}
err = GetServer().updateRules()
err = GetServer().UpdateRules()
return err
}
+7 -11
View File
@@ -11,7 +11,6 @@ import (
"time"
"github.com/gin-gonic/gin"
"github.com/li4n0/revsuit/internal/record"
"github.com/li4n0/revsuit/internal/recycler"
log "unknwon.dev/clog/v2"
)
@@ -26,18 +25,15 @@ func ping(c *gin.Context) {
c.String(200, "pong")
}
func events(c *gin.Context) {
log.Info("Receive client connection from %v", c.Request.RemoteAddr)
func (revsuit *Revsuit) events(c *gin.Context) {
id := revsuit.addClient(c)
log.Info("Receive client[id:%d] connection from %v", id, c.Request.RemoteAddr)
c.Stream(func(w io.Writer) bool {
select {
case <-c.Writer.CloseNotify():
return false
case r := <-record.Channel():
c.SSEvent("message", r.GetFlag())
}
return true
<-c.Writer.CloseNotify()
return false
})
log.Info("Client %s disconnect", c.Request.RemoteAddr)
revsuit.removeClient(id)
log.Info("Client[id:%d, remote_addr:%s] disconnect", id, c.Request.RemoteAddr)
}
func recovery(c *gin.Context) {
+2 -2
View File
@@ -40,7 +40,7 @@ func (revsuit *Revsuit) registerPlatformRouter() {
//platform routers
api.GET("/auth", auth)
api.GET("/events", events)
api.GET("/events", revsuit.events)
api.GET("/ping", ping)
api.GET("/version", version)
}
@@ -58,7 +58,7 @@ func (revsuit *Revsuit) registerHttpRouter() {
// init settings router group
settingsGroup := revsuit.http.ApiGroup.Group("setting")
settingsGroup.GET("/exportRules", exportRules)
settingsGroup.POST("/importRules", importRules)
settingsGroup.POST("/importRules", revsuit.importRules)
settingsGroup.GET("/getPlatformConfig", revsuit.getPlatformConfig)
settingsGroup.POST("/updatePlatformConfig", revsuit.updatePlatformConfig)
settingsGroup.GET("/getDnsConfig", revsuit.getDnsConfig)
+41 -2
View File
@@ -1,10 +1,13 @@
package server
import (
"sync"
"github.com/gin-gonic/gin"
"github.com/li4n0/revsuit/internal/database"
"github.com/li4n0/revsuit/internal/file"
"github.com/li4n0/revsuit/internal/notice"
"github.com/li4n0/revsuit/internal/record"
"github.com/li4n0/revsuit/pkg/dns"
"github.com/li4n0/revsuit/pkg/ftp"
"github.com/li4n0/revsuit/pkg/mysql"
@@ -14,7 +17,7 @@ import (
log "unknwon.dev/clog/v2"
)
const VERSION = "0.1.2-beta"
const VERSION = "0.1.3-beta"
type Revsuit struct {
config *Config
@@ -25,6 +28,29 @@ type Revsuit struct {
mysql *mysql.Server
rmi *rmi.Server
ftp *ftp.Server
clients map[int]*gin.Context
clientID int
clientsLock sync.RWMutex
clientsNum chan struct{}
}
func (revsuit *Revsuit) addClient(c *gin.Context) int {
revsuit.clientsLock.Lock()
defer revsuit.clientsLock.Unlock()
revsuit.clientID++
revsuit.clients[revsuit.clientID] = c
revsuit.clientsNum <- struct{}{}
return revsuit.clientID
}
func (revsuit *Revsuit) removeClient(id int) {
revsuit.clientsLock.Lock()
defer revsuit.clientsLock.Unlock()
delete(revsuit.clients, id)
<-revsuit.clientsNum
}
func initDatabase(dsn string) {
@@ -188,6 +214,8 @@ func New(c *Config) *Revsuit {
s.dns.SetServerIP(c.ExternalIP)
s.ftp.SetPasvIP(c.ExternalIP)
}
s.clients = make(map[int]*gin.Context)
s.clientsNum = make(chan struct{}, 100)
return s
}
@@ -207,6 +235,17 @@ func (revsuit *Revsuit) Run() {
if revsuit.ftp != nil && revsuit.ftp.Enable {
go revsuit.ftp.Run()
}
go func() {
for r := range record.Channel() {
<-revsuit.clientsNum
revsuit.clientsLock.RLock()
for _, client := range revsuit.clients {
client.SSEvent("message", r.GetFlag())
client.Writer.Flush()
}
revsuit.clientsNum <- struct{}{}
revsuit.clientsLock.RUnlock()
}
}()
revsuit.http.Run()
}
+26 -16
View File
@@ -45,7 +45,7 @@ func exportRules(c *gin.Context) {
c.String(200, string(out))
}
func importRules(c *gin.Context) {
func (revsuit *Revsuit) importRules(c *gin.Context) {
var (
db = database.DB
rules Rules
@@ -87,48 +87,58 @@ func importRules(c *gin.Context) {
}
for _, rule := range rules.Http {
err := db.Model(&rhttp.Rule{}).Create(&rule).Error
if err != nil {
if err := db.Model(&rhttp.Rule{}).Create(&rule).Error; err != nil {
errs = append(errs, errors.Wrap(err, fmt.Sprintf("http rule[%s]", rule.Name)).Error())
continue
}
count += 1
count++
}
if err := revsuit.http.UpdateRules(); err != nil {
errs = append(errs, err.Error())
}
for _, rule := range rules.Dns {
err := db.Model(&dns.Rule{}).Create(&rule).Error
if err != nil {
if err := db.Model(&dns.Rule{}).Create(&rule).Error; err != nil {
errs = append(errs, errors.Wrap(err, fmt.Sprintf("dns rule[%s]", rule.Name)).Error())
continue
}
count += 1
count++
}
if err := revsuit.dns.UpdateRules(); err != nil {
errs = append(errs, err.Error())
}
for _, rule := range rules.Mysql {
err := db.Model(&mysql.Rule{}).Create(&rule).Error
if err != nil {
if err := db.Model(&mysql.Rule{}).Create(&rule).Error; err != nil {
errs = append(errs, errors.Wrap(err, fmt.Sprintf("mysql rule[%s]", rule.Name)).Error())
continue
}
count += 1
count++
}
if err := revsuit.mysql.UpdateRules(); err != nil {
errs = append(errs, err.Error())
}
for _, rule := range rules.Rmi {
err := db.Model(&rmi.Rule{}).Create(&rule).Error
if err != nil {
if err := db.Model(&rmi.Rule{}).Create(&rule).Error; err != nil {
errs = append(errs, errors.Wrap(err, fmt.Sprintf("rmi rule[%s]", rule.Name)).Error())
continue
}
count += 1
count++
}
if err := revsuit.rmi.UpdateRules(); err != nil {
errs = append(errs, err.Error())
}
for _, rule := range rules.Ftp {
err := db.Model(&ftp.Rule{}).Create(&rule).Error
if err != nil {
if err := db.Model(&ftp.Rule{}).Create(&rule).Error; err != nil {
errs = append(errs, errors.Wrap(err, fmt.Sprintf("ftp rule[%s]", rule.Name)).Error())
continue
}
count += 1
count++
}
if err := revsuit.ftp.UpdateRules(); err != nil {
errs = append(errs, err.Error())
}
c.JSON(200, gin.H{