Files
EdgeCommon/pkg/serverconfigs/server_config.go
GoEdgeLab 2f3981704e v1.4.1
2024-07-27 13:29:26 +08:00

458 lines
12 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package serverconfigs
import (
"context"
"encoding/json"
"errors"
"regexp"
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
"golang.org/x/net/idna"
)
var normalServerNameReg = regexp.MustCompile(`^[a-zA-Z0-9.-]+$`)
type ServerConfig struct {
Id int64 `yaml:"id" json:"id"` // ID
ClusterId int64 `yaml:"clusterId" json:"clusterId"` // 集群ID
UserId int64 `yaml:"userId" json:"userId"` // 用户ID
Type string `yaml:"type" json:"type"` // 类型
IsOn bool `yaml:"isOn" json:"isOn"` // 是否开启
Name string `yaml:"name" json:"name"` // 名称
Description string `yaml:"description" json:"description"` // 描述
AliasServerNames []string `yaml:"aliasServerNames" json:"aliasServerNames"` // 关联的域名比如CNAME之类的
ServerNames []*ServerNameConfig `yaml:"serverNames" json:"serverNames"` // 域名
CNameDomain string `yaml:"cnameDomain" json:"cnameDomain"` // CNAME末尾不带点.
CNameAsDomain bool `yaml:"cnameAsDomain" json:"cnameAsDomain"` // 启用CNAME域名访问
SupportCNAME bool `yaml:"supportCNAME" json:"supportCNAME"` // 是否支持CNAME
// 前端协议
HTTP *HTTPProtocolConfig `yaml:"http" json:"http"` // HTTP配置
HTTPS *HTTPSProtocolConfig `yaml:"https" json:"https"` // HTTPS配置
TCP *TCPProtocolConfig `yaml:"tcp" json:"tcp"` // TCP配置
TLS *TLSProtocolConfig `yaml:"tls" json:"tls"` // TLS配置
UDP *UDPProtocolConfig `yaml:"udp" json:"udp"` // UDP配置
// Web配置
Web *HTTPWebConfig `yaml:"web" json:"web"`
// 反向代理配置
ReverseProxyRef *ReverseProxyRef `yaml:"reverseProxyRef" json:"reverseProxyRef"`
ReverseProxy *ReverseProxyConfig `yaml:"reverseProxy" json:"reverseProxy"`
// WAF策略
HTTPFirewallPolicyId int64 `yaml:"httpFirewallPolicyId" json:"httpFirewallPolicyId"`
HTTPFirewallPolicy *firewallconfigs.HTTPFirewallPolicy `yaml:"httpFirewallPolicy" json:"httpFirewallPolicy"` // 通过 HTTPFirewallPolicyId 获取
// 缓存策略
HTTPCachePolicyId int64 `yaml:"httpCachePolicyId" json:"httpCachePolicyId"`
HTTPCachePolicy *HTTPCachePolicy `yaml:"httpCachePolicy" json:"httpCachePolicy"` // 通过 HTTPCachePolicyId 获取
// 流量限制
TrafficLimit *TrafficLimitConfig `yaml:"trafficLimit" json:"trafficLimit"`
TrafficLimitStatus *TrafficLimitStatus `yaml:"trafficLimitStatus" json:"trafficLimitStatus"`
// 套餐
UserPlan *UserPlanConfig `yaml:"userPlan" json:"userPlan"`
// 分组
Group *ServerGroupConfig `yaml:"group" json:"group"`
// UAM
UAM *UAMConfig `yaml:"uam" json:"uam"`
isInitialized bool
isOk bool
planId int64
}
// NewServerConfigFromJSON 从JSON中解析Server配置
func NewServerConfigFromJSON(data []byte) (*ServerConfig, error) {
config := &ServerConfig{}
err := json.Unmarshal(data, config)
return config, err
}
func NewServerConfig() *ServerConfig {
return &ServerConfig{}
}
func (this *ServerConfig) Init(ctx context.Context) (results []error) {
if this.isInitialized {
return
}
this.isInitialized = true
// 分解Group
if this.Group != nil && this.Group.IsOn {
// reverse proxy
if this.IsHTTPFamily() && this.Group.HTTPReverseProxyRef != nil && this.Group.HTTPReverseProxyRef.IsPrior {
this.ReverseProxyRef = this.Group.HTTPReverseProxyRef
this.ReverseProxy = this.Group.HTTPReverseProxy
}
if this.IsTCPFamily() && this.Group.TCPReverseProxyRef != nil && this.Group.TCPReverseProxyRef.IsPrior {
this.ReverseProxyRef = this.Group.TCPReverseProxyRef
this.ReverseProxy = this.Group.TCPReverseProxy
}
if this.IsUDPFamily() && this.Group.UDPReverseProxyRef != nil && this.Group.UDPReverseProxyRef.IsPrior {
this.ReverseProxyRef = this.Group.UDPReverseProxyRef
this.ReverseProxy = this.Group.UDPReverseProxy
}
// web
if this.Group.Web != nil {
if this.Web == nil {
this.Web = this.Group.Web
} else {
var groupWeb = this.Group.Web
// root
if groupWeb.Root != nil && groupWeb.Root.IsPrior {
this.Web.Root = groupWeb.Root
}
// waf
if groupWeb.FirewallRef != nil && groupWeb.FirewallRef.IsPrior {
this.Web.FirewallRef = groupWeb.FirewallRef
this.Web.FirewallPolicy = groupWeb.FirewallPolicy
}
// cache
if groupWeb.Cache != nil && groupWeb.Cache.IsPrior {
this.Web.Cache = groupWeb.Cache
}
// charset
if groupWeb.Charset != nil && groupWeb.Charset.IsPrior {
this.Web.Charset = groupWeb.Charset
}
// accessLog
if groupWeb.AccessLogRef != nil && groupWeb.AccessLogRef.IsPrior {
this.Web.AccessLogRef = groupWeb.AccessLogRef
}
// stat
if groupWeb.StatRef != nil && groupWeb.StatRef.IsPrior {
this.Web.StatRef = groupWeb.StatRef
}
// compression
if groupWeb.Compression != nil && groupWeb.Compression.IsPrior {
this.Web.Compression = groupWeb.Compression
}
// headers
if groupWeb.RequestHeaderPolicyRef != nil && groupWeb.RequestHeaderPolicyRef.IsPrior {
this.Web.RequestHeaderPolicyRef = groupWeb.RequestHeaderPolicyRef
this.Web.RequestHeaderPolicy = groupWeb.RequestHeaderPolicy
}
if groupWeb.ResponseHeaderPolicyRef != nil && groupWeb.ResponseHeaderPolicyRef.IsPrior {
this.Web.ResponseHeaderPolicyRef = groupWeb.ResponseHeaderPolicyRef
this.Web.ResponseHeaderPolicy = groupWeb.ResponseHeaderPolicy
}
// websocket
if groupWeb.WebsocketRef != nil && groupWeb.WebsocketRef.IsPrior {
this.Web.WebsocketRef = groupWeb.WebsocketRef
this.Web.Websocket = groupWeb.Websocket
}
// webp
if groupWeb.WebP != nil && groupWeb.WebP.IsPrior {
this.Web.WebP = groupWeb.WebP
}
// remote addr
if groupWeb.RemoteAddr != nil && groupWeb.RemoteAddr.IsPrior {
this.Web.RemoteAddr = groupWeb.RemoteAddr
}
// pages
if len(groupWeb.Pages) > 0 || (groupWeb.Shutdown != nil && groupWeb.Shutdown.IsOn) {
this.Web.EnableGlobalPages = groupWeb.EnableGlobalPages
this.Web.Pages = groupWeb.Pages
this.Web.Shutdown = groupWeb.Shutdown
}
// request limit
if groupWeb.RequestLimit != nil && groupWeb.RequestLimit.IsPrior {
this.Web.RequestLimit = groupWeb.RequestLimit
}
}
}
}
if this.HTTP != nil {
err := this.HTTP.Init()
if err != nil {
results = append(results, err)
}
}
if this.HTTPS != nil {
err := this.HTTPS.Init(ctx)
if err != nil {
results = append(results, err)
}
}
if this.TCP != nil {
err := this.TCP.Init()
if err != nil {
results = append(results, err)
}
}
if this.TLS != nil {
err := this.TLS.Init(ctx)
if err != nil {
results = append(results, err)
}
}
if this.UDP != nil {
err := this.UDP.Init()
if err != nil {
results = append(results, err)
}
}
if this.ReverseProxyRef != nil {
err := this.ReverseProxyRef.Init()
if err != nil {
results = append(results, err)
}
}
if this.ReverseProxy != nil {
err := this.ReverseProxy.Init(ctx)
if err != nil {
results = append(results, err)
}
}
if this.Web != nil {
err := this.Web.Init(ctx)
if err != nil {
results = append(results, err)
}
}
// 套餐
if this.UserPlan != nil {
err := this.UserPlan.Init()
if err != nil {
results = append(results, err)
}
this.planId = this.UserPlan.PlanId
}
// UAM
if this.UAM != nil {
err := this.UAM.Init()
if err != nil {
results = append(results, err)
}
}
this.isOk = true
return
}
func (this *ServerConfig) IsInitialized() bool {
return this.isInitialized
}
// IsOk 配置是否正确
func (this *ServerConfig) IsOk() bool {
return this.isOk
}
func (this *ServerConfig) FullAddresses() []string {
result := []string{}
if this.HTTP != nil && this.HTTP.IsOn {
result = append(result, this.HTTP.FullAddresses()...)
}
if this.HTTPS != nil && this.HTTPS.IsOn {
result = append(result, this.HTTPS.FullAddresses()...)
}
if this.TCP != nil && this.TCP.IsOn {
result = append(result, this.TCP.FullAddresses()...)
}
if this.TLS != nil && this.TLS.IsOn {
result = append(result, this.TLS.FullAddresses()...)
}
if this.UDP != nil && this.UDP.IsOn {
result = append(result, this.UDP.FullAddresses()...)
}
return result
}
func (this *ServerConfig) Listen() []*NetworkAddressConfig {
result := []*NetworkAddressConfig{}
if this.HTTP != nil {
result = append(result, this.HTTP.Listen...)
}
if this.HTTPS != nil {
result = append(result, this.HTTPS.Listen...)
}
if this.TCP != nil {
result = append(result, this.TCP.Listen...)
}
if this.TLS != nil {
result = append(result, this.TLS.Listen...)
}
if this.UDP != nil {
result = append(result, this.UDP.Listen...)
}
return result
}
func (this *ServerConfig) AsJSON() ([]byte, error) {
return json.Marshal(this)
}
func (this *ServerConfig) IsHTTPFamily() bool {
return this.HTTP != nil || this.HTTPS != nil
}
func (this *ServerConfig) IsTCPFamily() bool {
return this.TCP != nil || this.TLS != nil
}
func (this *ServerConfig) IsUDPFamily() bool {
return this.UDP != nil
}
// AllStrictNames 所有严格域名
func (this *ServerConfig) AllStrictNames() []string {
var result = []string{}
for _, name := range this.AliasServerNames {
if len(name) > 0 {
if !configutils.IsFuzzyDomain(name) {
result = append(result, name)
// unicode domain
if !normalServerNameReg.MatchString(name) {
asciiName, err := idna.ToASCII(name)
if err == nil && len(asciiName) > 0 {
result = append(result, asciiName)
}
}
}
}
}
for _, serverName := range this.ServerNames {
var name = serverName.Name
if len(name) > 0 {
if !configutils.IsFuzzyDomain(name) {
result = append(result, name)
// unicode domain
if !normalServerNameReg.MatchString(name) {
asciiName, err := idna.ToASCII(name)
if err == nil && len(asciiName) > 0 {
result = append(result, asciiName)
}
}
}
}
for _, name := range serverName.SubNames {
if len(name) > 0 {
if !configutils.IsFuzzyDomain(name) {
result = append(result, name)
// unicode domain
if !normalServerNameReg.MatchString(name) {
asciiName, err := idna.ToASCII(name)
if err == nil && len(asciiName) > 0 {
result = append(result, asciiName)
}
}
}
}
}
}
return result
}
// AllFuzzyNames 所有模糊域名
func (this *ServerConfig) AllFuzzyNames() []string {
var result = []string{}
for _, name := range this.AliasServerNames {
if len(name) > 0 {
if configutils.IsFuzzyDomain(name) {
result = append(result, name)
}
}
}
for _, serverName := range this.ServerNames {
var name = serverName.Name
if len(name) > 0 {
if configutils.IsFuzzyDomain(name) {
result = append(result, name)
}
}
for _, name := range serverName.SubNames {
if len(name) > 0 {
if configutils.IsFuzzyDomain(name) {
result = append(result, name)
}
}
}
}
return result
}
// SSLPolicy SSL信息
func (this *ServerConfig) SSLPolicy() *sslconfigs.SSLPolicy {
if this.HTTPS != nil {
return this.HTTPS.SSLPolicy
}
if this.TLS != nil {
return this.TLS.SSLPolicy
}
return nil
}
// FindAndCheckReverseProxy 根据条件查找ReverseProxy
func (this *ServerConfig) FindAndCheckReverseProxy(dataType string) (*ReverseProxyConfig, error) {
switch dataType {
case "server":
if this.ReverseProxy == nil {
return nil, errors.New("reverse proxy not been configured")
}
return this.ReverseProxy, nil
default:
return nil, errors.New("invalid data type:'" + dataType + "'")
}
}
// ShouldCheckTrafficLimit 检查是否需要检查流量限制
func (this *ServerConfig) ShouldCheckTrafficLimit() bool {
return this.TrafficLimit != nil && !this.TrafficLimit.IsEmpty()
}
// PlanId 套餐ID
func (this *ServerConfig) PlanId() int64 {
return this.planId
}
// SupportsHTTP3 是否支持HTTP/3
func (this *ServerConfig) SupportsHTTP3() bool {
return this.isOk &&
this.HTTPS != nil &&
this.HTTPS.IsOn &&
this.HTTPS.SSLPolicy != nil &&
this.HTTPS.SSLPolicy.IsOn &&
this.HTTPS.SSLPolicy.HTTP3Enabled
}