improve reality setting

split xtls from tls - remove iran warp - remove old setting reality from franzkafka (it was a messy code) -and other improvement

Co-Authored-By: Alireza Ahmadi <alireza7@gmail.com>
This commit is contained in:
MHSanaei
2023-04-18 21:34:06 +03:30
parent dc7dbae14a
commit 3e0faecaae
20 changed files with 635 additions and 332 deletions
+110 -65
View File
@@ -64,28 +64,45 @@ func (s *InboundService) getClients(inbound *model.Inbound) ([]model.Client, err
return clients, nil
}
func (s *InboundService) checkEmailsExist(emails map[string]bool, ignoreId int) (string, error) {
func (s *InboundService) getAllEmails() ([]string, error) {
db := database.GetDB()
var inbounds []*model.Inbound
db = db.Model(model.Inbound{}).Where("Protocol in ?", []model.Protocol{model.VMess, model.VLESS, model.Trojan})
if ignoreId > 0 {
db = db.Where("id != ?", ignoreId)
}
db = db.Find(&inbounds)
if db.Error != nil {
return "", db.Error
}
var emails []string
err := db.Raw(`
SELECT JSON_EXTRACT(client.value, '$.email')
FROM inbounds,
JSON_EACH(JSON_EXTRACT(inbounds.settings, '$.clients')) AS client
`).Scan(&emails).Error
for _, inbound := range inbounds {
clients, err := s.getClients(inbound)
if err != nil {
return "", err
if err != nil {
return nil, err
}
return emails, nil
}
func (s *InboundService) contains(slice []string, str string) bool {
for _, s := range slice {
if s == str {
return true
}
}
return false
}
for _, client := range clients {
if emails[client.Email] {
func (s *InboundService) checkEmailsExistForClients(clients []model.Client) (string, error) {
allEmails, err := s.getAllEmails()
if err != nil {
return "", err
}
var emails []string
for _, client := range clients {
if client.Email != "" {
if s.contains(emails, client.Email) {
return client.Email, nil
}
if s.contains(allEmails, client.Email) {
return client.Email, nil
}
emails = append(emails, client.Email)
}
}
return "", nil
@@ -96,16 +113,23 @@ func (s *InboundService) checkEmailExistForInbound(inbound *model.Inbound) (stri
if err != nil {
return "", err
}
emails := make(map[string]bool)
allEmails, err := s.getAllEmails()
if err != nil {
return "", err
}
var emails []string
for _, client := range clients {
if client.Email != "" {
if emails[client.Email] {
if s.contains(emails, client.Email) {
return client.Email, nil
}
emails[client.Email] = true
if s.contains(allEmails, client.Email) {
return client.Email, nil
}
emails = append(emails, client.Email)
}
}
return s.checkEmailsExist(emails, inbound.Id)
return "", nil
}
func (s *InboundService) AddInbound(inbound *model.Inbound) (*model.Inbound, error) {
@@ -215,14 +239,6 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound,
return inbound, common.NewError("Port already exists:", inbound.Port)
}
existEmail, err := s.checkEmailExistForInbound(inbound)
if err != nil {
return inbound, err
}
if existEmail != "" {
return inbound, common.NewError("Duplicate email:", existEmail)
}
oldInbound, err := s.GetInbound(inbound.Id)
if err != nil {
return inbound, err
@@ -245,8 +261,12 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound,
return inbound, db.Save(oldInbound).Error
}
func (s *InboundService) AddInboundClient(inbound *model.Inbound) error {
existEmail, err := s.checkEmailExistForInbound(inbound)
func (s *InboundService) AddInboundClient(data *model.Inbound) error {
clients, err := s.getClients(data)
if err != nil {
return err
}
existEmail, err := s.checkEmailsExistForClients(clients)
if err != nil {
return err
}
@@ -255,29 +275,35 @@ func (s *InboundService) AddInboundClient(inbound *model.Inbound) error {
return common.NewError("Duplicate email:", existEmail)
}
clients, err := s.getClients(inbound)
oldInbound, err := s.GetInbound(data.Id)
if err != nil {
return err
}
oldInbound, err := s.GetInbound(inbound.Id)
var settings map[string]interface{}
err = json.Unmarshal([]byte(oldInbound.Settings), &settings)
if err != nil {
return err
}
oldClients, err := s.getClients(oldInbound)
oldClients := settings["clients"].([]interface{})
var newClients []interface{}
for _, client := range clients {
newClients = append(newClients, client)
}
settings["clients"] = append(oldClients, newClients...)
newSettings, err := json.MarshalIndent(settings, "", " ")
if err != nil {
return err
}
oldInbound.Settings = inbound.Settings
oldInbound.Settings = string(newSettings)
if len(clients[len(clients)-1].Email) > 0 {
s.AddClientStat(inbound.Id, &clients[len(clients)-1])
}
for i := len(oldClients); i < len(clients); i++ {
if len(clients[i].Email) > 0 {
s.AddClientStat(inbound.Id, &clients[i])
for _, client := range clients {
if len(client.Email) > 0 {
s.AddClientStat(data.Id, &client)
}
}
db := database.GetDB()
@@ -309,21 +335,13 @@ func (s *InboundService) DelInboundClient(inbound *model.Inbound, email string)
return db.Save(oldInbound).Error
}
func (s *InboundService) UpdateInboundClient(inbound *model.Inbound, index int) error {
existEmail, err := s.checkEmailExistForInbound(inbound)
if err != nil {
return err
}
if existEmail != "" {
return common.NewError("Duplicate email:", existEmail)
}
clients, err := s.getClients(inbound)
func (s *InboundService) UpdateInboundClient(data *model.Inbound, index int) error {
clients, err := s.getClients(data)
if err != nil {
return err
}
oldInbound, err := s.GetInbound(inbound.Id)
oldInbound, err := s.GetInbound(data.Id)
if err != nil {
return err
}
@@ -333,13 +351,40 @@ func (s *InboundService) UpdateInboundClient(inbound *model.Inbound, index int)
return err
}
oldInbound.Settings = inbound.Settings
if len(clients[0].Email) > 0 && clients[0].Email != oldClients[index].Email {
existEmail, err := s.checkEmailsExistForClients(clients)
if err != nil {
return err
}
if existEmail != "" {
return common.NewError("Duplicate email:", existEmail)
}
}
var settings map[string]interface{}
err = json.Unmarshal([]byte(oldInbound.Settings), &settings)
if err != nil {
return err
}
settingsClients := settings["clients"].([]interface{})
var newClients []interface{}
newClients = append(newClients, clients[0])
settingsClients[index] = newClients[0]
settings["clients"] = settingsClients
newSettings, err := json.MarshalIndent(settings, "", " ")
if err != nil {
return err
}
oldInbound.Settings = string(newSettings)
db := database.GetDB()
if len(clients[index].Email) > 0 {
if len(clients[0].Email) > 0 {
if len(oldClients[index].Email) > 0 {
err = s.UpdateClientStat(oldClients[index].Email, &clients[index])
err = s.UpdateClientStat(oldClients[index].Email, &clients[0])
if err != nil {
return err
}
@@ -348,7 +393,7 @@ func (s *InboundService) UpdateInboundClient(inbound *model.Inbound, index int)
return err
}
} else {
s.AddClientStat(inbound.Id, &clients[index])
s.AddClientStat(data.Id, &clients[0])
}
} else {
err = s.DelClientStat(db, oldClients[index].Email)
@@ -507,6 +552,16 @@ func (s *InboundService) DisableInvalidInbounds() (int64, error) {
count := result.RowsAffected
return count, err
}
func (s *InboundService) DisableInvalidClients() (int64, error) {
db := database.GetDB()
now := time.Now().Unix() * 1000
result := db.Model(xray.ClientTraffic{}).
Where("((total > 0 and up + down >= total) or (expiry_time > 0 and expiry_time <= ?)) and enable = ?", now, true).
Update("enable", false)
err := result.Error
count := result.RowsAffected
return count, err
}
func (s *InboundService) RemoveOrphanedTraffics() {
db := database.GetDB()
db.Exec(`
@@ -518,16 +573,6 @@ func (s *InboundService) RemoveOrphanedTraffics() {
)
`)
}
func (s *InboundService) DisableInvalidClients() (int64, error) {
db := database.GetDB()
now := time.Now().Unix() * 1000
result := db.Model(xray.ClientTraffic{}).
Where("((total > 0 and up + down >= total) or (expiry_time > 0 and expiry_time <= ?)) and enable = ?", now, true).
Update("enable", false)
err := result.Error
count := result.RowsAffected
return count, err
}
func (s *InboundService) AddClientStat(inboundId int, client *model.Client) error {
db := database.GetDB()
+26
View File
@@ -390,3 +390,29 @@ func (s *ServerService) GetDb() ([]byte, error) {
return fileContents, nil
}
func (s *ServerService) GetNewX25519Cert() (interface{}, error) {
// Run the command
cmd := exec.Command(xray.GetBinaryPath(), "x25519")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
return nil, err
}
lines := strings.Split(out.String(), "\n")
privateKeyLine := strings.Split(lines[0], ":")
publicKeyLine := strings.Split(lines[1], ":")
privateKey := strings.TrimSpace(privateKeyLine[1])
publicKey := strings.TrimSpace(publicKeyLine[1])
keyPair := map[string]interface{}{
"privateKey": privateKey,
"publicKey": publicKey,
}
return keyPair, nil
}
+56 -14
View File
@@ -8,6 +8,7 @@ import (
"x-ui/database"
"x-ui/database/model"
"x-ui/logger"
"x-ui/xray"
"github.com/goccy/go-json"
"gorm.io/gorm"
@@ -18,12 +19,15 @@ type SubService struct {
inboundService InboundService
}
func (s *SubService) GetSubs(subId string, host string) ([]string, error) {
func (s *SubService) GetSubs(subId string, host string) ([]string, string, error) {
s.address = host
var result []string
var header string
var traffic xray.ClientTraffic
var clientTraffics []xray.ClientTraffic
inbounds, err := s.getInboundsBySubId(subId)
if err != nil {
return nil, err
return nil, "", err
}
for _, inbound := range inbounds {
clients, err := s.inboundService.getClients(inbound)
@@ -37,22 +41,60 @@ func (s *SubService) GetSubs(subId string, host string) ([]string, error) {
if client.SubID == subId {
link := s.getLink(inbound, client.Email)
result = append(result, link)
clientTraffics = append(clientTraffics, s.getClientTraffics(inbound.ClientStats, client.Email))
}
}
}
return result, nil
for index, clientTraffic := range clientTraffics {
if index == 0 {
traffic.Up = clientTraffic.Up
traffic.Down = clientTraffic.Down
traffic.Total = clientTraffic.Total
if clientTraffic.ExpiryTime > 0 {
traffic.ExpiryTime = clientTraffic.ExpiryTime
}
} else {
traffic.Up += clientTraffic.Up
traffic.Down += clientTraffic.Down
if traffic.Total == 0 || clientTraffic.Total == 0 {
traffic.Total = 0
} else {
traffic.Total += clientTraffic.Total
}
if clientTraffic.ExpiryTime != traffic.ExpiryTime {
traffic.ExpiryTime = 0
}
}
}
header = fmt.Sprintf("upload=%d;download=%d", traffic.Up, traffic.Down)
if traffic.Total > 0 {
header = header + fmt.Sprintf(";total=%d", traffic.Total)
}
if traffic.ExpiryTime > 0 {
header = header + fmt.Sprintf(";expire=%d", traffic.ExpiryTime)
}
return result, header, nil
}
func (s *SubService) getInboundsBySubId(subId string) ([]*model.Inbound, error) {
db := database.GetDB()
var inbounds []*model.Inbound
err := db.Model(model.Inbound{}).Where("settings like ?", fmt.Sprintf(`%%"subId": "%s"%%`, subId)).Find(&inbounds).Error
err := db.Model(model.Inbound{}).Preload("ClientStats").Where("settings like ?", fmt.Sprintf(`%%"subId": "%s"%%`, subId)).Find(&inbounds).Error
if err != nil && err != gorm.ErrRecordNotFound {
return nil, err
}
return inbounds, nil
}
func (s *SubService) getClientTraffics(traffics []xray.ClientTraffic, email string) xray.ClientTraffic {
for _, traffic := range traffics {
if traffic.Email == email {
return traffic
}
}
return xray.ClientTraffic{}
}
func (s *SubService) getLink(inbound *model.Inbound, email string) string {
switch inbound.Protocol {
case "vmess":
@@ -296,7 +338,7 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
if security == "xtls" {
params["security"] = "xtls"
xtlsSetting, _ := stream["XTLSSettings"].(map[string]interface{})
xtlsSetting, _ := stream["xtlsSettings"].(map[string]interface{})
alpns, _ := xtlsSetting["alpn"].([]interface{})
var alpn []string
for _, a := range alpns {
@@ -306,15 +348,15 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
params["alpn"] = strings.Join(alpn, ",")
}
XTLSSettings, _ := searchKey(xtlsSetting, "settings")
xtlsSettings, _ := searchKey(xtlsSetting, "settings")
if xtlsSetting != nil {
if sniValue, ok := searchKey(XTLSSettings, "serverName"); ok {
if sniValue, ok := searchKey(xtlsSettings, "serverName"); ok {
params["sni"], _ = sniValue.(string)
}
if fpValue, ok := searchKey(XTLSSettings, "fingerprint"); ok {
if fpValue, ok := searchKey(xtlsSettings, "fingerprint"); ok {
params["fp"], _ = fpValue.(string)
}
if insecure, ok := searchKey(XTLSSettings, "allowInsecure"); ok {
if insecure, ok := searchKey(xtlsSettings, "allowInsecure"); ok {
if insecure.(bool) {
params["allowInsecure"] = "1"
}
@@ -465,7 +507,7 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
if security == "xtls" {
params["security"] = "xtls"
xtlsSetting, _ := stream["XTLSSettings"].(map[string]interface{})
xtlsSetting, _ := stream["xtlsSettings"].(map[string]interface{})
alpns, _ := xtlsSetting["alpn"].([]interface{})
var alpn []string
for _, a := range alpns {
@@ -475,15 +517,15 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
params["alpn"] = strings.Join(alpn, ",")
}
XTLSSettings, _ := searchKey(xtlsSetting, "settings")
xtlsSettings, _ := searchKey(xtlsSetting, "settings")
if xtlsSetting != nil {
if sniValue, ok := searchKey(XTLSSettings, "serverName"); ok {
if sniValue, ok := searchKey(xtlsSettings, "serverName"); ok {
params["sni"], _ = sniValue.(string)
}
if fpValue, ok := searchKey(XTLSSettings, "fingerprint"); ok {
if fpValue, ok := searchKey(xtlsSettings, "fingerprint"); ok {
params["fp"], _ = fpValue.(string)
}
if insecure, ok := searchKey(XTLSSettings, "allowInsecure"); ok {
if insecure, ok := searchKey(xtlsSettings, "allowInsecure"); ok {
if insecure.(bool) {
params["allowInsecure"] = "1"
}