Merge pull request #261 from hamid-gh98/main

Support set db and bin folder path from env
This commit is contained in:
Ho3ein 2023-04-14 05:28:03 +03:30 committed by GitHub
commit b70ecc12b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 121 additions and 103 deletions

View file

@ -45,6 +45,22 @@ func IsDebug() bool {
return os.Getenv("XUI_DEBUG") == "true" return os.Getenv("XUI_DEBUG") == "true"
} }
func GetDBPath() string { func GetBinFolderPath() string {
return fmt.Sprintf("/etc/%s/%s.db", GetName(), GetName()) binFolderPath := os.Getenv("XUI_BIN_FOLDER")
if binFolderPath == "" {
binFolderPath = "bin"
}
return binFolderPath
}
func GetDBFolderPath() string {
dbFolderPath := os.Getenv("XUI_DB_FOLDER")
if dbFolderPath == "" {
dbFolderPath = "/etc/x-ui"
}
return dbFolderPath
}
func GetDBPath() string {
return fmt.Sprintf("%s/%s.db", GetDBFolderPath(), GetName())
} }

View file

@ -217,7 +217,7 @@ func main() {
v2uiCmd := flag.NewFlagSet("v2-ui", flag.ExitOnError) v2uiCmd := flag.NewFlagSet("v2-ui", flag.ExitOnError)
var dbPath string var dbPath string
v2uiCmd.StringVar(&dbPath, "db", "/etc/v2-ui/v2-ui.db", "set v2-ui db file path") v2uiCmd.StringVar(&dbPath, "db", fmt.Sprintf("%s/v2-ui.db", config.GetDBFolderPath()), "set v2-ui db file path")
settingCmd := flag.NewFlagSet("setting", flag.ExitOnError) settingCmd := flag.NewFlagSet("setting", flag.ExitOnError)
var port int var port int

View file

@ -1,28 +1,30 @@
package job package job
import ( import (
"x-ui/logger" "encoding/json"
"x-ui/web/service" "os"
"regexp"
ss "strings"
"x-ui/database" "x-ui/database"
"x-ui/database/model" "x-ui/database/model"
"os" "x-ui/logger"
ss "strings" "x-ui/web/service"
"regexp" "x-ui/xray"
"encoding/json" // "strconv"
// "strconv" "github.com/go-cmd/cmd"
"net"
"sort"
"strings" "strings"
"time" "time"
"net"
"github.com/go-cmd/cmd"
"sort"
) )
type CheckClientIpJob struct { type CheckClientIpJob struct {
xrayService service.XrayService xrayService service.XrayService
inboundService service.InboundService inboundService service.InboundService
} }
var job *CheckClientIpJob var job *CheckClientIpJob
var disAllowedIps []string var disAllowedIps []string
func NewCheckClientIpJob() *CheckClientIpJob { func NewCheckClientIpJob() *CheckClientIpJob {
job = new(CheckClientIpJob) job = new(CheckClientIpJob)
@ -34,94 +36,91 @@ func (j *CheckClientIpJob) Run() {
processLogFile() processLogFile()
// disAllowedIps = []string{"192.168.1.183","192.168.1.197"} // disAllowedIps = []string{"192.168.1.183","192.168.1.197"}
blockedIps := []byte(ss.Join(disAllowedIps,",")) blockedIps := []byte(ss.Join(disAllowedIps, ","))
err := os.WriteFile("./bin/blockedIPs", blockedIps, 0755) err := os.WriteFile(xray.GetBlockedIPsPath(), blockedIps, 0755)
checkError(err) checkError(err)
} }
func processLogFile() { func processLogFile() {
accessLogPath := GetAccessLogPath() accessLogPath := GetAccessLogPath()
if(accessLogPath == "") { if accessLogPath == "" {
logger.Warning("xray log not init in config.json") logger.Warning("xray log not init in config.json")
return return
} }
data, err := os.ReadFile(accessLogPath) data, err := os.ReadFile(accessLogPath)
InboundClientIps := make(map[string][]string) InboundClientIps := make(map[string][]string)
checkError(err) checkError(err)
// clean log // clean log
if err := os.Truncate(GetAccessLogPath(), 0); err != nil { if err := os.Truncate(GetAccessLogPath(), 0); err != nil {
checkError(err) checkError(err)
} }
lines := ss.Split(string(data), "\n") lines := ss.Split(string(data), "\n")
for _, line := range lines { for _, line := range lines {
ipRegx, _ := regexp.Compile(`[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+`) ipRegx, _ := regexp.Compile(`[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+`)
emailRegx, _ := regexp.Compile(`email:.+`) emailRegx, _ := regexp.Compile(`email:.+`)
matchesIp := ipRegx.FindString(line) matchesIp := ipRegx.FindString(line)
if(len(matchesIp) > 0) { if len(matchesIp) > 0 {
ip := string(matchesIp) ip := string(matchesIp)
if( ip == "127.0.0.1" || ip == "1.1.1.1") { if ip == "127.0.0.1" || ip == "1.1.1.1" {
continue continue
} }
matchesEmail := emailRegx.FindString(line) matchesEmail := emailRegx.FindString(line)
if(matchesEmail == "") { if matchesEmail == "" {
continue continue
} }
matchesEmail = ss.Split(matchesEmail, "email: ")[1] matchesEmail = ss.Split(matchesEmail, "email: ")[1]
if(InboundClientIps[matchesEmail] != nil) { if InboundClientIps[matchesEmail] != nil {
if(contains(InboundClientIps[matchesEmail],ip)){ if contains(InboundClientIps[matchesEmail], ip) {
continue continue
} }
InboundClientIps[matchesEmail] = append(InboundClientIps[matchesEmail],ip) InboundClientIps[matchesEmail] = append(InboundClientIps[matchesEmail], ip)
} else {
InboundClientIps[matchesEmail] = append(InboundClientIps[matchesEmail], ip)
}else{ }
InboundClientIps[matchesEmail] = append(InboundClientIps[matchesEmail],ip)
}
} }
} }
disAllowedIps = []string{} disAllowedIps = []string{}
for clientEmail, ips := range InboundClientIps { for clientEmail, ips := range InboundClientIps {
inboundClientIps,err := GetInboundClientIps(clientEmail) inboundClientIps, err := GetInboundClientIps(clientEmail)
sort.Sort(sort.StringSlice(ips)) sort.Sort(sort.StringSlice(ips))
if(err != nil){ if err != nil {
addInboundClientIps(clientEmail,ips) addInboundClientIps(clientEmail, ips)
}else{ } else {
updateInboundClientIps(inboundClientIps,clientEmail,ips) updateInboundClientIps(inboundClientIps, clientEmail, ips)
} }
}
}
// check if inbound connection is more than limited ip and drop connection // check if inbound connection is more than limited ip and drop connection
LimitDevice := func() { LimitDevice() } LimitDevice := func() { LimitDevice() }
stop := schedule(LimitDevice, 1000 *time.Millisecond) stop := schedule(LimitDevice, 1000*time.Millisecond)
time.Sleep(10 * time.Second) time.Sleep(10 * time.Second)
stop <- true stop <- true
} }
func GetAccessLogPath() string { func GetAccessLogPath() string {
config, err := os.ReadFile("bin/config.json") config, err := os.ReadFile(xray.GetConfigPath())
checkError(err) checkError(err)
jsonConfig := map[string]interface{}{} jsonConfig := map[string]interface{}{}
err = json.Unmarshal([]byte(config), &jsonConfig) err = json.Unmarshal([]byte(config), &jsonConfig)
checkError(err) checkError(err)
if(jsonConfig["log"] != nil) { if jsonConfig["log"] != nil {
jsonLog := jsonConfig["log"].(map[string]interface{}) jsonLog := jsonConfig["log"].(map[string]interface{})
if(jsonLog["access"] != nil) { if jsonLog["access"] != nil {
accessLogPath := jsonLog["access"].(string) accessLogPath := jsonLog["access"].(string)
@ -132,7 +131,7 @@ func GetAccessLogPath() string {
} }
func checkError(e error) { func checkError(e error) {
if e != nil { if e != nil {
logger.Warning("client ip job err:", e) logger.Warning("client ip job err:", e)
} }
} }
@ -182,20 +181,20 @@ func addInboundClientIps(clientEmail string, ips []string) error {
} }
return nil return nil
} }
func updateInboundClientIps(inboundClientIps *model.InboundClientIps,clientEmail string,ips []string) error { func updateInboundClientIps(inboundClientIps *model.InboundClientIps, clientEmail string, ips []string) error {
jsonIps, err := json.Marshal(ips) jsonIps, err := json.Marshal(ips)
checkError(err) checkError(err)
inboundClientIps.ClientEmail = clientEmail inboundClientIps.ClientEmail = clientEmail
inboundClientIps.Ips = string(jsonIps) inboundClientIps.Ips = string(jsonIps)
// check inbound limitation // check inbound limitation
inbound, err := GetInboundByEmail(clientEmail) inbound, err := GetInboundByEmail(clientEmail)
checkError(err) checkError(err)
if inbound.Settings == "" { if inbound.Settings == "" {
logger.Debug("wrong data ",inbound) logger.Debug("wrong data ", inbound)
return nil return nil
} }
@ -205,17 +204,17 @@ func updateInboundClientIps(inboundClientIps *model.InboundClientIps,clientEmail
for _, client := range clients { for _, client := range clients {
if client.Email == clientEmail { if client.Email == clientEmail {
limitIp := client.LimitIP limitIp := client.LimitIP
if(limitIp < len(ips) && limitIp != 0 && inbound.Enable) { if limitIp < len(ips) && limitIp != 0 && inbound.Enable {
disAllowedIps = append(disAllowedIps,ips[limitIp:]...) disAllowedIps = append(disAllowedIps, ips[limitIp:]...)
} }
} }
} }
logger.Debug("disAllowedIps ",disAllowedIps) logger.Debug("disAllowedIps ", disAllowedIps)
sort.Sort(sort.StringSlice(disAllowedIps)) sort.Sort(sort.StringSlice(disAllowedIps))
db := database.GetDB() db := database.GetDB()
err = db.Save(inboundClientIps).Error err = db.Save(inboundClientIps).Error
@ -224,13 +223,13 @@ func updateInboundClientIps(inboundClientIps *model.InboundClientIps,clientEmail
} }
return nil return nil
} }
func DisableInbound(id int) error{ func DisableInbound(id int) error {
db := database.GetDB() db := database.GetDB()
result := db.Model(model.Inbound{}). result := db.Model(model.Inbound{}).
Where("id = ? and enable = ?", id, true). Where("id = ? and enable = ?", id, true).
Update("enable", false) Update("enable", false)
err := result.Error err := result.Error
logger.Warning("disable inbound with id:",id) logger.Warning("disable inbound with id:", id)
if err == nil { if err == nil {
job.xrayService.SetToNeedRestart() job.xrayService.SetToNeedRestart()
@ -242,7 +241,7 @@ func DisableInbound(id int) error{
func GetInboundByEmail(clientEmail string) (*model.Inbound, error) { func GetInboundByEmail(clientEmail string) (*model.Inbound, error) {
db := database.GetDB() db := database.GetDB()
var inbounds *model.Inbound var inbounds *model.Inbound
err := db.Model(model.Inbound{}).Where("settings LIKE ?", "%" + clientEmail + "%").Find(&inbounds).Error err := db.Model(model.Inbound{}).Where("settings LIKE ?", "%"+clientEmail+"%").Find(&inbounds).Error
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -250,45 +249,44 @@ func GetInboundByEmail(clientEmail string) (*model.Inbound, error) {
} }
func LimitDevice() { func LimitDevice() {
var destIp, destPort, srcIp, srcPort string var destIp, destPort, srcIp, srcPort string
localIp,err := LocalIP()
checkError(err)
c := cmd.NewCmd("bash","-c","ss --tcp | grep -E '" + IPsToRegex(localIp) + "'| awk '{if($1==\"ESTAB\") print $4,$5;}'","| sort | uniq -c | sort -nr | head") localIp, err := LocalIP()
checkError(err)
<-c.Start() c := cmd.NewCmd("bash", "-c", "ss --tcp | grep -E '"+IPsToRegex(localIp)+"'| awk '{if($1==\"ESTAB\") print $4,$5;}'", "| sort | uniq -c | sort -nr | head")
if len(c.Status().Stdout) > 0 {
ipRegx, _ := regexp.Compile(`[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+`)
portRegx, _ := regexp.Compile(`(?:(:))([0-9]..[^.][0-9]+)`)
for _, row := range c.Status().Stdout { <-c.Start()
if len(c.Status().Stdout) > 0 {
ipRegx, _ := regexp.Compile(`[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+`)
portRegx, _ := regexp.Compile(`(?:(:))([0-9]..[^.][0-9]+)`)
data := strings.Split(row," ") for _, row := range c.Status().Stdout {
if len(data) < 2 { data := strings.Split(row, " ")
continue // Skip this row if it doesn't have at least two elements
}
destIp = string(ipRegx.FindString(data[0])) if len(data) < 2 {
destPort = portRegx.FindString(data[0]) continue // Skip this row if it doesn't have at least two elements
destPort = strings.Replace(destPort,":","",-1) }
srcIp = string(ipRegx.FindString(data[1])) destIp = string(ipRegx.FindString(data[0]))
srcPort = portRegx.FindString(data[1]) destPort = portRegx.FindString(data[0])
srcPort = strings.Replace(srcPort,":","",-1) destPort = strings.Replace(destPort, ":", "", -1)
if contains(disAllowedIps,srcIp){ srcIp = string(ipRegx.FindString(data[1]))
dropCmd := cmd.NewCmd("bash","-c","ss -K dport = " + srcPort) srcPort = portRegx.FindString(data[1])
dropCmd.Start() srcPort = strings.Replace(srcPort, ":", "", -1)
logger.Debug("request droped : ",srcIp,srcPort,"to",destIp,destPort) if contains(disAllowedIps, srcIp) {
} dropCmd := cmd.NewCmd("bash", "-c", "ss -K dport = "+srcPort)
} dropCmd.Start()
}
logger.Debug("request droped : ", srcIp, srcPort, "to", destIp, destPort)
}
}
}
} }
func LocalIP() ([]string, error) { func LocalIP() ([]string, error) {
// get machine ips // get machine ips
@ -312,24 +310,23 @@ func LocalIP() ([]string, error) {
ip = v.IP ip = v.IP
} }
ips = append(ips,ip.String()) ips = append(ips, ip.String())
} }
} }
logger.Debug("System IPs : ",ips) logger.Debug("System IPs : ", ips)
return ips, nil return ips, nil
} }
func IPsToRegex(ips []string) string {
func IPsToRegex(ips []string) (string){
regx := "" regx := ""
for _, ip := range ips { for _, ip := range ips {
regx += "(" + strings.Replace(ip, ".", "\\.", -1) + ")" regx += "(" + strings.Replace(ip, ".", "\\.", -1) + ")"
} }
regx = "(" + strings.Replace(regx, ")(", ")|(.", -1) + ")" regx = "(" + strings.Replace(regx, ")(", ")|(.", -1) + ")"
return regx return regx
} }

View file

@ -106,8 +106,8 @@
"expireDate" = "Expire date" "expireDate" = "Expire date"
"resetTraffic" = "Reset traffic" "resetTraffic" = "Reset traffic"
"addInbound" = "Add Inbound" "addInbound" = "Add Inbound"
"addTo" = "Add To" "addTo" = "Create"
"revise" = "Revise" "revise" = "Update"
"modifyInbound" = "Modify InBound" "modifyInbound" = "Modify InBound"
"deleteInbound" = "Delete Inbound" "deleteInbound" = "Delete Inbound"
"deleteInboundContent" = "Are you sure you want to delete inbound?" "deleteInboundContent" = "Are you sure you want to delete inbound?"

View file

@ -14,6 +14,7 @@ import (
"runtime" "runtime"
"strings" "strings"
"time" "time"
"x-ui/config"
"x-ui/util/common" "x-ui/util/common"
"github.com/Workiva/go-datastructures/queue" "github.com/Workiva/go-datastructures/queue"
@ -29,19 +30,23 @@ func GetBinaryName() string {
} }
func GetBinaryPath() string { func GetBinaryPath() string {
return "bin/" + GetBinaryName() return config.GetBinFolderPath() + "/" + GetBinaryName()
} }
func GetConfigPath() string { func GetConfigPath() string {
return "bin/config.json" return config.GetBinFolderPath() + "/config.json"
} }
func GetGeositePath() string { func GetGeositePath() string {
return "bin/geosite.dat" return config.GetBinFolderPath() + "/geosite.dat"
} }
func GetGeoipPath() string { func GetGeoipPath() string {
return "bin/geoip.dat" return config.GetBinFolderPath() + "/geoip.dat"
}
func GetBlockedIPsPath() string {
return config.GetBinFolderPath() + "/blockedIPs"
} }
func stopProcess(p *Process) { func stopProcess(p *Process) {
@ -162,7 +167,7 @@ func (p *process) Start() (err error) {
return common.NewErrorf("Failed to write configuration file: %v", err) return common.NewErrorf("Failed to write configuration file: %v", err)
} }
cmd := exec.Command(GetBinaryPath(), "-c", configPath, "-restrictedIPsPath", "./bin/blockedIPs") cmd := exec.Command(GetBinaryPath(), "-c", configPath, "-restrictedIPsPath", GetBlockedIPsPath())
p.cmd = cmd p.cmd = cmd
stdReader, err := cmd.StdoutPipe() stdReader, err := cmd.StdoutPipe()