2020-11-25 21:19:22 +08:00
package setup
import (
2021-07-14 22:46:23 +08:00
"encoding/json"
2024-07-27 14:15:25 +08:00
"strconv"
"strings"
2020-12-03 18:19:22 +08:00
"github.com/TeaOSLab/EdgeAPI/internal/acme"
2021-01-20 14:19:29 +08:00
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
2022-02-18 12:58:26 +08:00
"github.com/TeaOSLab/EdgeAPI/internal/db/models/stats"
2020-11-25 21:19:22 +08:00
"github.com/TeaOSLab/EdgeAPI/internal/errors"
2021-08-29 16:01:31 +08:00
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
2021-07-14 22:46:23 +08:00
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
2021-09-29 20:12:53 +08:00
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
2021-08-06 14:22:17 +08:00
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
2023-12-20 17:34:54 +08:00
"github.com/TeaOSLab/EdgeCommon/pkg/userconfigs"
2020-11-25 21:19:22 +08:00
"github.com/iwind/TeaGo/dbs"
2021-01-20 14:19:29 +08:00
"github.com/iwind/TeaGo/lists"
2021-07-14 22:46:23 +08:00
"github.com/iwind/TeaGo/maps"
2020-12-14 21:25:11 +08:00
"github.com/iwind/TeaGo/rands"
2020-11-25 21:19:22 +08:00
"github.com/iwind/TeaGo/types"
)
type upgradeVersion struct {
version string
f func ( db * dbs . DB ) error
}
var upgradeFuncs = [ ] * upgradeVersion {
{
"0.0.3" , upgradeV0_0_3 ,
} ,
2020-12-03 18:19:22 +08:00
{
"0.0.5" , upgradeV0_0_5 ,
} ,
2020-12-14 21:25:11 +08:00
{
"0.0.6" , upgradeV0_0_6 ,
} ,
2021-01-20 14:19:29 +08:00
{
"0.0.9" , upgradeV0_0_9 ,
} ,
2021-02-02 19:29:36 +08:00
{
"0.0.10" , upgradeV0_0_10 ,
} ,
2021-07-11 18:05:57 +08:00
{
"0.2.5" , upgradeV0_2_5 ,
} ,
2021-08-06 14:22:17 +08:00
{
2021-08-09 13:57:58 +08:00
"0.2.8.1" , upgradeV0_2_8_1 ,
2021-08-06 14:22:17 +08:00
} ,
2021-08-29 16:01:31 +08:00
{
"0.3.0" , upgradeV0_3_0 ,
} ,
2021-09-08 17:31:18 +08:00
{
"0.3.1" , upgradeV0_3_1 ,
} ,
2021-09-29 20:12:53 +08:00
{
"0.3.2" , upgradeV0_3_2 ,
} ,
2021-10-25 12:01:16 +08:00
{
"0.3.3" , upgradeV0_3_3 ,
} ,
2021-12-06 19:27:11 +08:00
{
"0.3.7" , upgradeV0_3_7 ,
} ,
2022-01-10 20:07:26 +08:00
{
"0.4.0" , upgradeV0_4_0 ,
} ,
2022-01-23 19:16:52 +08:00
{
"0.4.1" , upgradeV0_4_1 ,
} ,
2022-03-09 10:01:24 +08:00
{
"0.4.5" , upgradeV0_4_5 ,
} ,
2022-04-14 16:44:00 +08:00
{
"0.4.7" , upgradeV0_4_7 ,
} ,
2022-06-15 19:22:33 +08:00
{
"0.4.8" , upgradeV0_4_8 ,
} ,
2022-07-07 12:40:05 +08:00
{
"0.4.9" , upgradeV0_4_9 ,
} ,
2022-07-27 16:56:17 +08:00
{
"0.4.11" , upgradeV0_4_11 ,
} ,
2022-09-09 15:25:32 +08:00
{
2022-11-06 12:03:11 +08:00
"0.5.3" , upgradeV0_5_3 ,
2022-09-09 15:25:32 +08:00
} ,
2022-10-14 10:03:29 +08:00
{
2022-11-06 12:03:11 +08:00
"0.5.6" , upgradeV0_5_6 ,
} ,
{
2022-11-11 17:48:30 +08:00
"0.5.8" , upgradeV0_5_8 ,
2022-10-14 10:03:29 +08:00
} ,
2023-07-02 14:30:46 +08:00
{
"1.2.1" , upgradeV1_2_1 ,
} ,
2023-09-06 16:30:47 +08:00
{
"1.2.9" , upgradeV1_2_9 ,
} ,
2023-09-18 16:09:11 +08:00
{
2023-10-15 15:10:36 +08:00
"1.2.10" , upgradeV1_2_10 ,
2023-09-18 16:09:11 +08:00
} ,
2023-12-12 17:15:21 +08:00
{
2023-12-24 17:40:40 +08:00
"1.3.2" , upgradeV1_3_2 ,
2023-12-12 17:15:21 +08:00
} ,
2024-03-18 12:43:13 +08:00
{
"1.3.4" , upgradeV1_3_4 ,
} ,
2020-11-25 21:19:22 +08:00
}
2021-07-11 18:05:57 +08:00
// UpgradeSQLData 升级SQL数据
2020-11-25 21:19:22 +08:00
func UpgradeSQLData ( db * dbs . DB ) error {
version , err := db . FindCol ( 0 , "SELECT version FROM edgeVersions" )
if err != nil {
return err
}
2024-04-14 11:47:10 +08:00
var versionString = types . String ( version )
2020-11-25 21:19:22 +08:00
if len ( versionString ) > 0 {
for _ , f := range upgradeFuncs {
2024-04-14 11:47:10 +08:00
if CompareVersion ( versionString , f . version ) >= 0 {
2020-11-25 21:19:22 +08:00
continue
}
err = f . f ( db )
if err != nil {
return err
}
}
}
return nil
}
// v0.0.3
func upgradeV0_0_3 ( db * dbs . DB ) error {
// 获取第一个管理员
adminIdCol , err := db . FindCol ( 0 , "SELECT id FROM edgeAdmins ORDER BY id ASC LIMIT 1" )
if err != nil {
return err
}
adminId := types . Int64 ( adminIdCol )
if adminId <= 0 {
return errors . New ( "'edgeAdmins' table should not be empty" )
}
// 升级edgeDNSProviders
_ , err = db . Exec ( "UPDATE edgeDNSProviders SET adminId=? WHERE adminId=0 AND userId=0" , adminId )
if err != nil {
return err
}
2020-11-27 09:57:21 +08:00
// 升级edgeDNSDomains
_ , err = db . Exec ( "UPDATE edgeDNSDomains SET adminId=? WHERE adminId=0 AND userId=0" , adminId )
if err != nil {
return err
}
2020-11-25 21:19:22 +08:00
// 升级edgeSSLCerts
_ , err = db . Exec ( "UPDATE edgeSSLCerts SET adminId=? WHERE adminId=0 AND userId=0" , adminId )
if err != nil {
return err
}
2020-11-27 09:57:21 +08:00
// 升级edgeNodeClusters
_ , err = db . Exec ( "UPDATE edgeNodeClusters SET adminId=? WHERE adminId=0 AND userId=0" , adminId )
if err != nil {
return err
}
// 升级edgeNodes
_ , err = db . Exec ( "UPDATE edgeNodes SET adminId=? WHERE adminId=0 AND userId=0" , adminId )
if err != nil {
return err
}
2020-11-27 10:02:46 +08:00
// 升级edgeNodeGrants
_ , err = db . Exec ( "UPDATE edgeNodeGrants SET adminId=? WHERE adminId=0" , adminId )
if err != nil {
return err
}
2020-11-25 21:19:22 +08:00
return nil
}
2020-12-03 18:19:22 +08:00
2020-12-14 21:25:11 +08:00
// v0.0.5
2020-12-03 18:19:22 +08:00
func upgradeV0_0_5 ( db * dbs . DB ) error {
// 升级edgeACMETasks
_ , err := db . Exec ( "UPDATE edgeACMETasks SET authType=? WHERE authType IS NULL OR LENGTH(authType)=0" , acme . AuthTypeDNS )
if err != nil {
return err
}
return nil
}
2020-12-14 21:25:11 +08:00
// v0.0.6
func upgradeV0_0_6 ( db * dbs . DB ) error {
stmt , err := db . Prepare ( "SELECT COUNT(*) FROM edgeAPITokens WHERE role='user'" )
if err != nil {
return err
}
defer func ( ) {
_ = stmt . Close ( )
} ( )
col , err := stmt . FindCol ( 0 )
if err != nil {
return err
}
count := types . Int ( col )
if count > 0 {
return nil
}
nodeId := rands . HexString ( 32 )
secret := rands . String ( 32 )
_ , err = db . Exec ( "INSERT INTO edgeAPITokens (nodeId, secret, role) VALUES (?, ?, ?)" , nodeId , secret , "user" )
if err != nil {
return err
}
return nil
}
2021-01-20 14:19:29 +08:00
// v0.0.9
func upgradeV0_0_9 ( db * dbs . DB ) error {
// firewall policies
var tx * dbs . Tx
dbs . NotifyReady ( )
policies , err := models . NewHTTPFirewallPolicyDAO ( ) . FindAllEnabledFirewallPolicies ( tx )
if err != nil {
return err
}
for _ , policy := range policies {
if policy . ServerId > 0 {
continue
}
policyId := int64 ( policy . Id )
webIds , err := models . NewHTTPWebDAO ( ) . FindAllWebIdsWithHTTPFirewallPolicyId ( tx , policyId )
if err != nil {
return err
}
serverIds := [ ] int64 { }
for _ , webId := range webIds {
serverId , err := models . NewServerDAO ( ) . FindEnabledServerIdWithWebId ( tx , webId )
if err != nil {
return err
}
if serverId > 0 && ! lists . ContainsInt64 ( serverIds , serverId ) {
serverIds = append ( serverIds , serverId )
}
}
if len ( serverIds ) == 1 {
err = models . NewHTTPFirewallPolicyDAO ( ) . UpdateFirewallPolicyServerId ( tx , policyId , serverIds [ 0 ] )
if err != nil {
return err
}
}
}
return nil
}
2021-02-02 19:29:36 +08:00
// v0.0.10
func upgradeV0_0_10 ( db * dbs . DB ) error {
return nil
}
2021-07-11 18:05:57 +08:00
// v0.2.5
func upgradeV0_2_5 ( db * dbs . DB ) error {
2021-07-14 22:46:23 +08:00
// 更新用户
_ , err := db . Exec ( "UPDATE edgeUsers SET day=FROM_UNIXTIME(createdAt,'%Y%m%d') WHERE day IS NULL OR LENGTH(day)=0" )
2021-07-11 18:05:57 +08:00
if err != nil {
return err
}
2021-07-14 22:46:23 +08:00
// 更新防火墙规则
ones , _ , err := db . FindOnes ( "SELECT id, actions, action, actionOptions FROM edgeHTTPFirewallRuleSets WHERE actions IS NULL OR LENGTH(actions)=0" )
if err != nil {
return err
}
for _ , one := range ones {
oneId := one . GetInt64 ( "id" )
action := one . GetString ( "action" )
options := one . GetString ( "actionOptions" )
var optionsMap = maps . Map { }
if len ( options ) > 0 {
_ = json . Unmarshal ( [ ] byte ( options ) , & optionsMap )
}
var actions = [ ] * firewallconfigs . HTTPFirewallActionConfig {
{
Code : action ,
Options : optionsMap ,
} ,
}
actionsJSON , err := json . Marshal ( actions )
if err != nil {
return err
}
_ , err = db . Exec ( "UPDATE edgeHTTPFirewallRuleSets SET actions=? WHERE id=?" , string ( actionsJSON ) , oneId )
if err != nil {
return err
}
}
2021-07-11 18:05:57 +08:00
return nil
}
2021-08-06 14:22:17 +08:00
2021-08-29 16:01:31 +08:00
// v0.3.0
func upgradeV0_3_0 ( db * dbs . DB ) error {
// 升级健康检查
ones , _ , err := db . FindOnes ( "SELECT id,healthCheck FROM edgeNodeClusters WHERE state=1" )
if err != nil {
return err
}
for _ , one := range ones {
var clusterId = one . GetInt64 ( "id" )
var healthCheck = one . GetString ( "healthCheck" )
if len ( healthCheck ) == 0 {
continue
}
var config = & serverconfigs . HealthCheckConfig { }
err = json . Unmarshal ( [ ] byte ( healthCheck ) , config )
if err != nil {
continue
}
if config . CountDown <= 1 {
config . CountDown = 3
configJSON , err := json . Marshal ( config )
if err != nil {
continue
}
_ , err = db . Exec ( "UPDATE edgeNodeClusters SET healthCheck=? WHERE id=?" , string ( configJSON ) , clusterId )
if err != nil {
return err
}
}
}
return nil
}
2021-09-08 17:31:18 +08:00
// v0.3.1
func upgradeV0_3_1 ( db * dbs . DB ) error {
2021-09-12 20:21:42 +08:00
// 清空域名统计,已使用分表代替
2021-09-16 15:43:07 +08:00
// 因为可能有权限问题,所以我们忽略错误
2021-09-08 17:31:18 +08:00
_ , _ = db . Exec ( "TRUNCATE table edgeServerDomainHourlyStats" )
2021-09-16 15:43:07 +08:00
// 升级APIToken
ones , _ , err := db . FindOnes ( "SELECT uniqueId,secret FROM edgeNodeClusters" )
if err != nil {
return err
}
for _ , one := range ones {
var uniqueId = one . GetString ( "uniqueId" )
var secret = one . GetString ( "secret" )
tokenOne , err := db . FindOne ( "SELECT id FROM edgeAPITokens WHERE nodeId=? LIMIT 1" , uniqueId )
if err != nil {
return err
}
if len ( tokenOne ) == 0 {
_ , err = db . Exec ( "INSERT INTO edgeAPITokens (nodeId, secret, role, state) VALUES (?, ?, 'cluster', 1)" , uniqueId , secret )
if err != nil {
return err
}
}
}
2021-09-08 17:31:18 +08:00
return nil
}
2021-09-29 20:12:53 +08:00
// v0.3.2
func upgradeV0_3_2 ( db * dbs . DB ) error {
// gzip => compression
type HTTPGzipRef struct {
IsPrior bool ` yaml:"isPrior" json:"isPrior" ` // 是否覆盖
IsOn bool ` yaml:"isOn" json:"isOn" ` // 是否开启
GzipId int64 ` yaml:"gzipId" json:"gzipId" ` // 使用的配置ID
}
2021-10-29 14:02:40 +08:00
webOnes , _ , err := db . FindOnes ( "SELECT id, gzip FROM edgeHTTPWebs WHERE gzip IS NOT NULL AND compression IS NULL" )
2021-09-29 20:12:53 +08:00
if err != nil {
return err
}
for _ , webOne := range webOnes {
var gzipRef = & HTTPGzipRef { }
err = json . Unmarshal ( [ ] byte ( webOne . GetString ( "gzip" ) ) , gzipRef )
if err != nil {
continue
}
if gzipRef == nil || gzipRef . GzipId <= 0 {
continue
}
var webId = webOne . GetInt ( "id" )
var compressionConfig = & serverconfigs . HTTPCompressionConfig {
UseDefaultTypes : true ,
}
compressionConfig . IsPrior = gzipRef . IsPrior
compressionConfig . IsOn = gzipRef . IsOn
gzipOne , err := db . FindOne ( "SELECT * FROM edgeHTTPGzips WHERE id=?" , gzipRef . GzipId )
if err != nil {
return err
}
if len ( gzipOne ) == 0 {
continue
}
level := gzipOne . GetInt ( "level" )
if level <= 0 {
continue
}
if level > 0 && level <= 10 {
compressionConfig . Level = types . Int8 ( level )
} else if level > 10 {
compressionConfig . Level = 10
}
var minLengthBytes = [ ] byte ( gzipOne . GetString ( "minLength" ) )
if len ( minLengthBytes ) > 0 {
var sizeCapacity = & shared . SizeCapacity { }
err = json . Unmarshal ( minLengthBytes , sizeCapacity )
if err != nil {
continue
}
2023-08-08 16:46:17 +08:00
compressionConfig . MinLength = sizeCapacity
2021-09-29 20:12:53 +08:00
}
var maxLengthBytes = [ ] byte ( gzipOne . GetString ( "maxLength" ) )
if len ( maxLengthBytes ) > 0 {
var sizeCapacity = & shared . SizeCapacity { }
err = json . Unmarshal ( maxLengthBytes , sizeCapacity )
if err != nil {
continue
}
2023-08-08 16:46:17 +08:00
compressionConfig . MaxLength = sizeCapacity
2021-09-29 20:12:53 +08:00
}
var condsBytes = [ ] byte ( gzipOne . GetString ( "conds" ) )
if len ( condsBytes ) > 0 {
var conds = & shared . HTTPRequestCondsConfig { }
err = json . Unmarshal ( condsBytes , conds )
if err != nil {
continue
}
2023-08-08 16:46:17 +08:00
compressionConfig . Conds = conds
2021-09-29 20:12:53 +08:00
}
configJSON , err := json . Marshal ( compressionConfig )
if err != nil {
return err
}
_ , err = db . Exec ( "UPDATE edgeHTTPWebs SET compression=? WHERE id=?" , string ( configJSON ) , webId )
if err != nil {
return err
}
}
2021-10-10 16:29:50 +08:00
// 更新服务端口
var serverDAO = models . NewServerDAO ( )
ones , err := serverDAO . Query ( nil ) .
ResultPk ( ) .
FindAll ( )
if err != nil {
return err
}
for _ , one := range ones {
var serverId = int64 ( one . ( * models . Server ) . Id )
err = serverDAO . NotifyServerPortsUpdate ( nil , serverId )
if err != nil {
return err
}
}
2021-09-29 20:12:53 +08:00
return nil
}
2021-10-25 12:01:16 +08:00
// v0.3.3
func upgradeV0_3_3 ( db * dbs . DB ) error {
// 升级CC请求数Code
_ , err := db . Exec ( "UPDATE edgeHTTPFirewallRuleSets SET code='8002' WHERE name='CC请求数' AND code='8001'" )
if err != nil {
return err
}
2021-11-01 16:03:40 +08:00
// 清除节点
// 删除7天以前的info日志
err = models . NewNodeLogDAO ( ) . DeleteExpiredLogsWithLevel ( nil , "info" , 7 )
if err != nil {
return err
}
2021-10-25 12:01:16 +08:00
return nil
}
2021-12-06 19:27:11 +08:00
// v0.3.7
func upgradeV0_3_7 ( db * dbs . DB ) error {
// 修改所有edgeNodeGrants中的su为0
_ , err := db . Exec ( "UPDATE edgeNodeGrants SET su=0 WHERE su=1" )
if err != nil {
return err
}
2021-12-12 20:24:36 +08:00
// WAF预置分组
_ , err = db . Exec ( "UPDATE edgeHTTPFirewallRuleGroups SET isTemplate=1 WHERE LENGTH(code)>0" )
if err != nil {
return err
}
2021-12-06 19:27:11 +08:00
return nil
2021-12-12 20:24:36 +08:00
}
2022-01-10 20:07:26 +08:00
// v0.4.0
func upgradeV0_4_0 ( db * dbs . DB ) error {
// 升级SYN Flood配置
2024-04-07 14:21:01 +08:00
synFloodJSON , err := json . Marshal ( firewallconfigs . NewSYNFloodConfig ( ) )
2022-01-10 20:07:26 +08:00
if err == nil {
_ , err := db . Exec ( "UPDATE edgeHTTPFirewallPolicies SET synFlood=? WHERE synFlood IS NULL AND state=1" , string ( synFloodJSON ) )
if err != nil {
return err
}
}
return nil
}
2022-01-23 19:16:52 +08:00
// v0.4.1
func upgradeV0_4_1 ( db * dbs . DB ) error {
// 升级 servers.lastUserPlanId
_ , err := db . Exec ( "UPDATE edgeServers SET lastUserPlanId=userPlanId WHERE userPlanId>0" )
if err != nil {
return err
}
2022-02-18 12:58:26 +08:00
// 执行域名统计清理
2023-07-01 17:54:40 +08:00
err = stats . NewServerDomainHourlyStatDAO ( ) . CleanDays ( nil , 7 )
2022-02-18 12:58:26 +08:00
if err != nil {
return err
}
2022-01-23 19:16:52 +08:00
return nil
}
2022-03-09 10:01:24 +08:00
// v0.4.5
func upgradeV0_4_5 ( db * dbs . DB ) error {
// 升级访问日志自动分表
{
var dao = models . NewSysSettingDAO ( )
valueJSON , err := dao . ReadSetting ( nil , systemconfigs . SettingCodeAccessLogQueue )
if err != nil {
return err
}
if len ( valueJSON ) > 0 {
var config = & serverconfigs . AccessLogQueueConfig { }
err = json . Unmarshal ( valueJSON , config )
2022-03-20 11:54:17 +08:00
if err == nil && config . RowsPerTable == 0 {
2022-03-09 10:01:24 +08:00
config . EnableAutoPartial = true
config . RowsPerTable = 500_000
configJSON , err := json . Marshal ( config )
if err == nil {
err = dao . UpdateSetting ( nil , systemconfigs . SettingCodeAccessLogQueue , configJSON )
if err != nil {
return err
}
}
}
}
}
2022-04-14 16:44:00 +08:00
// 升级一个防SQL注入规则
2022-03-20 11:54:17 +08:00
{
2022-04-14 16:44:00 +08:00
ones , _ , err := db . FindOnes ( ` SELECT id FROM edgeHTTPFirewallRules WHERE value=? ` , "(updatexml|extractvalue|ascii|ord|char|chr|count|concat|rand|floor|substr|length|len|user|database|benchmark|analyse)\\s*\\(" )
2022-03-20 11:54:17 +08:00
if err != nil {
return err
}
for _ , one := range ones {
var ruleId = one . GetInt64 ( "id" )
2022-04-14 16:44:00 +08:00
_ , err = db . Exec ( ` UPDATE edgeHTTPFirewallRules SET value=? WHERE id=? LIMIT 1 ` , ` \b(updatexml|extractvalue|ascii|ord|char|chr|count|concat|rand|floor|substr|length|len|user|database|benchmark|analyse)\s*\(.*\) ` , ruleId )
2022-03-20 11:54:17 +08:00
if err != nil {
return err
}
}
}
2022-03-09 10:01:24 +08:00
return nil
}
2022-04-14 16:44:00 +08:00
// v0.4.7
func upgradeV0_4_7 ( db * dbs . DB ) error {
// 升级 edgeServers 中的 plainServerNames
{
ones , _ , err := db . FindOnes ( "SELECT id,serverNames FROM edgeServers WHERE state=1" )
if err != nil {
return err
}
for _ , one := range ones {
var serverId = one . GetInt64 ( "id" )
var serverNamesJSON = one . GetBytes ( "serverNames" )
if len ( serverNamesJSON ) > 0 {
var serverNames = [ ] * serverconfigs . ServerNameConfig { }
err = json . Unmarshal ( serverNamesJSON , & serverNames )
if err != nil {
return err
}
plainServerNamesJSON , err := json . Marshal ( serverconfigs . PlainServerNames ( serverNames ) )
if err != nil {
return err
}
_ , err = db . Exec ( "UPDATE edgeServers SET plainServerNames=? WHERE id=?" , plainServerNamesJSON , serverId )
if err != nil {
return err
}
}
}
}
return nil
}
2022-06-15 19:22:33 +08:00
2022-07-07 12:40:05 +08:00
// v0.4.8
2022-06-15 19:22:33 +08:00
func upgradeV0_4_8 ( db * dbs . DB ) error {
// 设置edgeIPLists中的serverId
{
firewallPolicyOnes , _ , err := db . FindOnes ( "SELECT inbound,serverId FROM edgeHTTPFirewallPolicies WHERE serverId>0" )
if err != nil {
return err
}
for _ , one := range firewallPolicyOnes {
var inboundBytes = one . GetBytes ( "inbound" )
var serverId = one . GetInt64 ( "serverId" )
var listIds = [ ] int64 { }
if len ( inboundBytes ) > 0 {
var inbound = & firewallconfigs . HTTPFirewallInboundConfig { }
err = json . Unmarshal ( inboundBytes , inbound )
if err == nil { // we ignore errors
if inbound . AllowListRef != nil && inbound . AllowListRef . ListId > 0 {
listIds = append ( listIds , inbound . AllowListRef . ListId )
}
if inbound . DenyListRef != nil && inbound . DenyListRef . ListId > 0 {
listIds = append ( listIds , inbound . DenyListRef . ListId )
}
if inbound . GreyListRef != nil && inbound . GreyListRef . ListId > 0 {
listIds = append ( listIds , inbound . GreyListRef . ListId )
}
}
}
if len ( listIds ) == 0 {
continue
}
for _ , listId := range listIds {
isPublicCol , err := db . FindCol ( 0 , "SELECT isPublic FROM edgeIPLists WHERE id=? LIMIT 1" , listId )
if err != nil {
return err
}
var isPublic = types . Bool ( isPublicCol )
if ! isPublic {
_ , err = db . Exec ( "UPDATE edgeIPLists SET serverId=? WHERE id=?" , serverId , listId )
if err != nil {
return err
}
}
}
}
}
return nil
}
2022-07-07 12:40:05 +08:00
2022-07-27 16:56:17 +08:00
// v0.4.11
func upgradeV0_4_11 ( db * dbs . DB ) error {
// 升级ns端口
{
// TCP
{
var config = & serverconfigs . TCPProtocolConfig { }
config . IsOn = true
config . Listen = [ ] * serverconfigs . NetworkAddressConfig {
{
Protocol : serverconfigs . ProtocolTCP ,
PortRange : "53" ,
} ,
}
configJSON , err := json . Marshal ( config )
if err != nil {
return err
}
_ , err = db . Exec ( "UPDATE edgeNSClusters SET tcp=? WHERE tcp IS NULL" , configJSON )
if err != nil {
return err
}
}
// UDP
{
var config = & serverconfigs . UDPProtocolConfig { }
config . IsOn = true
config . Listen = [ ] * serverconfigs . NetworkAddressConfig {
{
Protocol : serverconfigs . ProtocolUDP ,
PortRange : "53" ,
} ,
}
configJSON , err := json . Marshal ( config )
if err != nil {
return err
}
_ , err = db . Exec ( "UPDATE edgeNSClusters SET udp=? WHERE udp IS NULL" , configJSON )
if err != nil {
return err
}
}
}
return nil
}
2023-07-02 14:30:46 +08:00
// v1.2.1
func upgradeV1_2_1 ( db * dbs . DB ) error {
// upgrade generated USER-xxx in old versions
ones , _ , err := db . FindOnes ( "SELECT id, username, clusterId FROM edgeUsers WHERE username LIKE 'USER-%'" )
if err != nil {
return err
}
for _ , one := range ones {
var userId = one . GetInt64 ( "id" )
var clusterId = one . GetInt64 ( "clusterId" )
var username = one . GetString ( "username" )
if clusterId <= 0 {
defaultClusterIdValue , err := db . FindCol ( 0 , "SELECT id FROM edgeNodeClusters WHERE state=1 ORDER BY id ASC LIMIT 1" )
if err != nil {
return err
}
var defaultClusterId = types . Int64 ( defaultClusterIdValue )
if defaultClusterId > 0 {
_ , err = db . Exec ( "UPDATE edgeUsers SET username=?, clusterId=? WHERE id=?" , strings . ReplaceAll ( username , "-" , "_" ) , defaultClusterId , userId )
if err != nil {
return err
}
}
}
}
return nil
}
2023-09-18 16:09:11 +08:00
// 1.2.10
func upgradeV1_2_10 ( db * dbs . DB ) error {
{
type OldGlobalConfig struct {
// HTTP & HTTPS相关配置
HTTPAll struct {
DomainAuditingIsOn bool ` yaml:"domainAuditingIsOn" json:"domainAuditingIsOn" ` // 域名是否需要审核
DomainAuditingPrompt string ` yaml:"domainAuditingPrompt" json:"domainAuditingPrompt" ` // 域名审核的提示
} ` yaml:"httpAll" json:"httpAll" `
TCPAll struct {
PortRangeMin int ` yaml:"portRangeMin" json:"portRangeMin" ` // 最小端口
PortRangeMax int ` yaml:"portRangeMax" json:"portRangeMax" ` // 最大端口
DenyPorts [ ] int ` yaml:"denyPorts" json:"denyPorts" ` // 禁止使用的端口
} ` yaml:"tcpAll" json:"tcpAll" `
}
globalConfigValue , err := db . FindCol ( 0 , "SELECT value FROM edgeSysSettings WHERE code='serverGlobalConfig'" )
if err != nil {
return err
}
var globalConfigString = types . String ( globalConfigValue )
if len ( globalConfigString ) > 0 {
var oldGlobalConfig = & OldGlobalConfig { }
err = json . Unmarshal ( [ ] byte ( globalConfigString ) , oldGlobalConfig )
if err == nil { // we ignore error
ones , _ , err := db . FindOnes ( "SELECT id,globalServerConfig FROM edgeNodeClusters" )
if err != nil {
return err
}
for _ , one := range ones {
var id = one . GetInt64 ( "id" )
var globalServerConfigData = [ ] byte ( one . GetString ( "globalServerConfig" ) )
if len ( globalServerConfigData ) > 32 {
var globalServerConfig = & serverconfigs . GlobalServerConfig { }
err = json . Unmarshal ( globalServerConfigData , globalServerConfig )
if err != nil {
return err
}
2023-09-18 16:55:45 +08:00
2023-09-18 16:09:11 +08:00
globalServerConfig . HTTPAll . DomainAuditingIsOn = oldGlobalConfig . HTTPAll . DomainAuditingIsOn
globalServerConfig . HTTPAll . DomainAuditingPrompt = oldGlobalConfig . HTTPAll . DomainAuditingPrompt
2023-09-18 16:55:45 +08:00
globalServerConfig . TCPAll . DenyPorts = oldGlobalConfig . TCPAll . DenyPorts
globalServerConfig . TCPAll . PortRangeMin = oldGlobalConfig . TCPAll . PortRangeMin
globalServerConfig . TCPAll . PortRangeMax = oldGlobalConfig . TCPAll . PortRangeMax
2023-09-18 16:09:11 +08:00
globalServerConfigJSON , err := json . Marshal ( globalServerConfig )
if err != nil {
return err
}
_ , err = db . Exec ( "UPDATE edgeNodeClusters SET globalServerConfig=? WHERE id=?" , globalServerConfigJSON , id )
if err != nil {
return err
}
}
}
}
}
}
return nil
}
2023-12-12 17:15:21 +08:00
// 1.3.2
func upgradeV1_3_2 ( db * dbs . DB ) error {
// waf
{
var disableSet = func ( setId int64 ) error {
_ , err := db . Exec ( "UPDATE edgeHTTPFirewallRuleSets SET state=0 WHERE id=?" , setId )
return err
}
var addRuleToGroup = func ( groupId int64 , setCode string , setName string , actions [ ] * firewallconfigs . HTTPFirewallActionConfig , ruleParam string , ruleOperator string , value string ) error {
actionsJSON , err := json . Marshal ( actions )
if err != nil {
return err
}
// rule
ruleResult , err := db . Exec ( "INSERT INTO edgeHTTPFirewallRules (isOn, param, operator, value, isCaseInsensitive, state) VALUES (1, ?, ?, ?, 0, 1)" , ruleParam , ruleOperator , value )
if err != nil {
return err
}
ruleId , err := ruleResult . LastInsertId ( )
if err != nil {
return err
}
var ruleRefs = [ ] * firewallconfigs . HTTPFirewallRuleRef {
{
IsOn : true ,
RuleId : ruleId ,
} ,
}
ruleRefsJSON , err := json . Marshal ( ruleRefs )
if err != nil {
return err
}
// set
setResult , err := db . Exec ( "INSERT INTO edgeHTTPFirewallRuleSets (isOn, code, name, rules, connector, state, actions) VALUES (1, ?, ?, ?, 'or', 1, ?)" , setCode , setName , ruleRefsJSON , actionsJSON )
if err != nil {
return err
}
setId , err := setResult . LastInsertId ( )
if err != nil {
return err
}
var setRefs = [ ] * firewallconfigs . HTTPFirewallRuleSetRef {
{
IsOn : true ,
SetId : setId ,
} ,
}
setRefsJSON , err := json . Marshal ( setRefs )
if err != nil {
return err
}
// group
_ , err = db . Exec ( "UPDATE edgeHTTPFirewallRuleGroups SET sets=? WHERE id=?" , setRefsJSON , groupId )
if err != nil {
return err
}
return nil
}
// sql injection
{
ruleGroups , _ , err := db . FindOnes ( "SELECT id, sets FROM edgeHTTPFirewallRuleGroups WHERE code='sqlInjection' AND state=1" )
if err != nil {
return err
}
for _ , ruleGroup := range ruleGroups {
var setsJSON = ruleGroup . GetBytes ( "sets" )
if len ( setsJSON ) == 0 {
continue
}
var setRefs = [ ] * firewallconfigs . HTTPFirewallRuleSetRef { }
err = json . Unmarshal ( setsJSON , & setRefs )
if err != nil {
continue
}
if len ( setRefs ) != 5 {
continue
}
var isChanged = false
for setIndex , setRef := range setRefs {
set , setErr := db . FindOne ( "SELECT id, rules, isOn, actions FROM edgeHTTPFirewallRuleSets WHERE id=? AND state=1" , setRef . SetId )
if setErr != nil {
return setErr
}
if set == nil {
isChanged = true
break
}
var rulesJSON = set . GetBytes ( "rules" )
if len ( rulesJSON ) == 0 {
isChanged = true
break
}
var ruleRefs = [ ] * firewallconfigs . HTTPFirewallRuleRef { }
err = json . Unmarshal ( rulesJSON , & ruleRefs )
if err != nil {
return err
}
if len ( ruleRefs ) < 1 {
isChanged = true
break
}
var actionsJSON = set . GetBytes ( "actions" )
if len ( actionsJSON ) == 0 {
isChanged = true
break
}
var actions = [ ] * firewallconfigs . HTTPFirewallActionConfig { }
err = json . Unmarshal ( actionsJSON , & actions )
if err != nil {
return err
}
if ! ( len ( actions ) == 1 && actions [ 0 ] . Code == firewallconfigs . HTTPFirewallActionBlock ) {
isChanged = true
break
}
var rules = [ ] maps . Map { }
for _ , ruleRef := range ruleRefs {
rule , ruleErr := db . FindOne ( "SELECT * FROM edgeHTTPFirewallRules WHERE id=? AND state=1" , ruleRef . RuleId )
if ruleErr != nil {
return ruleErr
}
if rule == nil {
isChanged = true
break
}
rules = append ( rules , rule )
}
if isChanged {
break
}
if len ( rules ) < 1 {
isChanged = true
break
}
switch setIndex {
case 0 :
var rule = rules [ 0 ]
if ! ( rule . GetString ( "param" ) == "${requestAll}" && rule . GetString ( "operator" ) == "match" && rule . GetString ( "value" ) == ` union[\s/\*]+select ` ) {
isChanged = true
}
case 1 :
var rule = rules [ 0 ]
if ! ( rule . GetString ( "param" ) == "${requestAll}" && rule . GetString ( "operator" ) == "match" && rule . GetString ( "value" ) == ` /\*(!|\x00) ` ) {
isChanged = true
}
case 2 :
if len ( rules ) != 4 {
isChanged = true
} else {
{
var rule = rules [ 0 ]
if ! ( rule . GetString ( "param" ) == "${requestAll}" && rule . GetString ( "operator" ) == "match" && rule . GetString ( "value" ) == ` \s(and|or|rlike)\s+(if|updatexml)\s*\( ` ) {
isChanged = true
}
}
{
var rule = rules [ 1 ]
if ! ( rule . GetString ( "param" ) == "${requestAll}" && rule . GetString ( "operator" ) == "match" && rule . GetString ( "value" ) == ` \s+(and|or|rlike)\s+(select|case)\s+ ` ) {
isChanged = true
}
}
{
var rule = rules [ 2 ]
if ! ( rule . GetString ( "param" ) == "${requestAll}" && rule . GetString ( "operator" ) == "match" && rule . GetString ( "value" ) == ` \s+(and|or|procedure)\s+[\w\p { L}]+\s*=\s*[\w\p { L}]+(\s|$|--|#) ` ) {
isChanged = true
}
}
{
var rule = rules [ 3 ]
if ! ( rule . GetString ( "param" ) == "${requestAll}" && rule . GetString ( "operator" ) == "match" && rule . GetString ( "value" ) == ` \(\s*case\s+when\s+[\w\p { L}]+\s*=\s*[\w\p { L}]+\s+then\s+ ` ) {
isChanged = true
}
}
}
case 3 :
var rule = rules [ 0 ]
if ! ( rule . GetString ( "param" ) == "${requestAll}" && rule . GetString ( "operator" ) == "match" && rule . GetString ( "value" ) == ` \b(updatexml|extractvalue|ascii|ord|char|chr|count|concat|rand|floor|substr|length|len|user|database|benchmark|analyse)\s*\(.*\) ` ) {
isChanged = true
}
case 4 :
var rule = rules [ 0 ]
if ! ( rule . GetString ( "param" ) == "${requestAll}" && rule . GetString ( "operator" ) == "match" && rule . GetString ( "value" ) == ` ;\s*(declare|use|drop|create|exec|delete|update|insert)\s ` ) {
isChanged = true
}
}
}
if isChanged {
continue
}
for _ , setRef := range setRefs {
err = disableSet ( setRef . SetId )
if err != nil {
return err
}
}
err = addRuleToGroup ( ruleGroup . GetInt64 ( "id" ) , "7010" , "SQL注入检测" , [ ] * firewallconfigs . HTTPFirewallActionConfig {
{
Code : firewallconfigs . HTTPFirewallActionPage ,
Options : maps . Map { "status" : 403 , "body" : "" } ,
} ,
} , "${requestAll}" , firewallconfigs . HTTPFirewallRuleOperatorContainsSQLInjection , "" )
if err != nil {
return err
}
}
}
// xss
{
ruleGroups , _ , err := db . FindOnes ( "SELECT id, sets FROM edgeHTTPFirewallRuleGroups WHERE code='xss' AND state=1" )
if err != nil {
return err
}
for _ , ruleGroup := range ruleGroups {
var setsJSON = ruleGroup . GetBytes ( "sets" )
if len ( setsJSON ) == 0 {
continue
}
var setRefs = [ ] * firewallconfigs . HTTPFirewallRuleSetRef { }
err = json . Unmarshal ( setsJSON , & setRefs )
if err != nil {
continue
}
if len ( setRefs ) != 3 {
continue
}
var isChanged = false
for setIndex , setRef := range setRefs {
set , setErr := db . FindOne ( "SELECT id, rules, isOn, actions FROM edgeHTTPFirewallRuleSets WHERE id=? AND state=1" , setRef . SetId )
if setErr != nil {
return setErr
}
if set == nil {
isChanged = true
break
}
var rulesJSON = set . GetBytes ( "rules" )
if len ( rulesJSON ) == 0 {
isChanged = true
break
}
var ruleRefs = [ ] * firewallconfigs . HTTPFirewallRuleRef { }
err = json . Unmarshal ( rulesJSON , & ruleRefs )
if err != nil {
return err
}
if len ( ruleRefs ) != 1 {
isChanged = true
break
}
var actionsJSON = set . GetBytes ( "actions" )
if len ( actionsJSON ) == 0 {
isChanged = true
break
}
var actions = [ ] * firewallconfigs . HTTPFirewallActionConfig { }
err = json . Unmarshal ( actionsJSON , & actions )
if err != nil {
return err
}
if ! ( len ( actions ) == 1 && actions [ 0 ] . Code == firewallconfigs . HTTPFirewallActionBlock ) {
isChanged = true
break
}
rule , ruleErr := db . FindOne ( "SELECT * FROM edgeHTTPFirewallRules WHERE id=? AND state=1" , ruleRefs [ 0 ] . RuleId )
if ruleErr != nil {
return ruleErr
}
if rule == nil {
isChanged = true
break
}
switch setIndex {
case 0 :
if ! ( rule . GetString ( "param" ) == "${requestURI}" && rule . GetString ( "operator" ) == "match" && rule . GetString ( "value" ) == ` (onmouseover|onmousemove|onmousedown|onmouseup|onerror|onload|onclick|ondblclick|onkeydown|onkeyup|onkeypress)\s*= ` ) {
isChanged = true
}
case 1 :
if ! ( rule . GetString ( "param" ) == "${requestURI}" && rule . GetString ( "operator" ) == "match" && rule . GetString ( "value" ) == ` (alert|eval|prompt|confirm)\s*\( ` ) {
isChanged = true
}
case 2 :
if ! ( rule . GetString ( "param" ) == "${requestURI}" && rule . GetString ( "operator" ) == "match" && rule . GetString ( "value" ) == ` <(script|iframe|link) ` ) {
isChanged = true
}
}
}
if isChanged {
continue
}
for _ , setRef := range setRefs {
err = disableSet ( setRef . SetId )
if err != nil {
return err
}
}
err = addRuleToGroup ( ruleGroup . GetInt64 ( "id" ) , "1010" , "XSS攻击检测" , [ ] * firewallconfigs . HTTPFirewallActionConfig {
{
Code : firewallconfigs . HTTPFirewallActionPage ,
Options : maps . Map { "status" : 403 , "body" : "" } ,
} ,
} , "${requestAll}" , firewallconfigs . HTTPFirewallRuleOperatorContainsXSS , "" )
if err != nil {
return err
}
}
}
}
2023-12-20 17:34:54 +08:00
// user register config
var newAddedFeatureCodes = [ ] string {
userconfigs . UserFeatureCodeServerOptimization ,
userconfigs . UserFeatureCodeServerAuth ,
userconfigs . UserFeatureCodeServerWebsocket ,
userconfigs . UserFeatureCodeServerHTTP3 ,
userconfigs . UserFeatureCodeServerCC ,
userconfigs . UserFeatureCodeServerReferers ,
userconfigs . UserFeatureCodeServerUserAgent ,
userconfigs . UserFeatureCodeServerRequestLimit ,
userconfigs . UserFeatureCodeServerCompression ,
userconfigs . UserFeatureCodeServerRewriteRules ,
userconfigs . UserFeatureCodeServerHostRedirects ,
userconfigs . UserFeatureCodeServerHTTPHeaders ,
userconfigs . UserFeatureCodeServerPages ,
}
{
value , err := db . FindCol ( 0 , "SELECT value FROM edgeSysSettings WHERE code=?" , systemconfigs . SettingCodeUserRegisterConfig )
if err != nil {
return err
}
if value != nil {
var valueString = types . String ( value )
if valueString != "null" && len ( valueString ) > 0 {
var registerConfig = & userconfigs . UserRegisterConfig { }
err = json . Unmarshal ( [ ] byte ( valueString ) , registerConfig )
if err != nil {
return err
}
if len ( registerConfig . Features ) > 0 {
var newFeatureCodes = registerConfig . Features
var changed = false
for _ , featureCode := range newAddedFeatureCodes {
if ! lists . ContainsString ( newFeatureCodes , featureCode ) {
newFeatureCodes = append ( newFeatureCodes , featureCode )
changed = true
}
}
if changed {
registerConfig . Features = newFeatureCodes
registerConfigJSON , err := json . Marshal ( registerConfig )
if err != nil {
return err
}
_ , err = db . Exec ( "UPDATE edgeSysSettings SET value=? WHERE code=?" , registerConfigJSON , systemconfigs . SettingCodeUserRegisterConfig )
if err != nil {
return err
}
}
}
}
}
}
// user features
{
var sqlPieces [ ] string
for _ , featureCode := range newAddedFeatureCodes {
if strings . Contains ( featureCode , "'" ) {
continue
}
sqlPieces = append ( sqlPieces , "'$', '" + featureCode + "'" )
}
_ , err := db . Exec ( "UPDATE edgeUsers SET features=JSON_ARRAY_APPEND(features," + strings . Join ( sqlPieces , "," ) + ") WHERE features IS NOT NULL AND JSON_LENGTH(features)>0 AND NOT JSON_CONTAINS(features, '" + strconv . Quote ( newAddedFeatureCodes [ 0 ] ) + "')" )
if err != nil {
return err
}
}
2023-12-12 17:15:21 +08:00
return nil
}
2024-03-18 12:43:13 +08:00
// 1.3.4
func upgradeV1_3_4 ( db * dbs . DB ) error {
_ , err := db . Exec ( "DELETE FROM edgeLoginSessions WHERE adminId>0" )
if err != nil {
return err
}
return nil
}