// Copyright 2023 The frp Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package legacy import ( "strings" "github.com/samber/lo" "github.com/fatedier/frp/pkg/config/types" v1 "github.com/fatedier/frp/pkg/config/v1" ) func Convert_ClientCommonConf_To_v1(conf *ClientCommonConf) *v1.ClientCommonConfig { out := &v1.ClientCommonConfig{} out.User = conf.User out.Auth.Method = v1.AuthMethod(conf.ClientConfig.AuthenticationMethod) out.Auth.Token = conf.ClientConfig.Token if conf.ClientConfig.AuthenticateHeartBeats { out.Auth.AdditionalScopes = append(out.Auth.AdditionalScopes, v1.AuthScopeHeartBeats) } if conf.ClientConfig.AuthenticateNewWorkConns { out.Auth.AdditionalScopes = append(out.Auth.AdditionalScopes, v1.AuthScopeNewWorkConns) } out.Auth.OIDC.ClientID = conf.ClientConfig.OidcClientID out.Auth.OIDC.ClientSecret = conf.ClientConfig.OidcClientSecret out.Auth.OIDC.Audience = conf.ClientConfig.OidcAudience out.Auth.OIDC.Scope = conf.ClientConfig.OidcScope out.Auth.OIDC.TokenEndpointURL = conf.ClientConfig.OidcTokenEndpointURL out.Auth.OIDC.AdditionalEndpointParams = conf.ClientConfig.OidcAdditionalEndpointParams out.ServerAddr = conf.ServerAddr out.ServerPort = conf.ServerPort out.NatHoleSTUNServer = conf.NatHoleSTUNServer out.Transport.DialServerTimeout = conf.DialServerTimeout out.Transport.DialServerKeepAlive = conf.DialServerKeepAlive out.Transport.ConnectServerLocalIP = conf.ConnectServerLocalIP out.Transport.ProxyURL = conf.HTTPProxy out.Transport.PoolCount = conf.PoolCount out.Transport.TCPMux = lo.ToPtr(conf.TCPMux) out.Transport.TCPMuxKeepaliveInterval = conf.TCPMuxKeepaliveInterval out.Transport.Protocol = conf.Protocol out.Transport.HeartbeatInterval = conf.HeartbeatInterval out.Transport.HeartbeatTimeout = conf.HeartbeatTimeout out.Transport.QUIC.KeepalivePeriod = conf.QUICKeepalivePeriod out.Transport.QUIC.MaxIdleTimeout = conf.QUICMaxIdleTimeout out.Transport.QUIC.MaxIncomingStreams = conf.QUICMaxIncomingStreams out.Transport.TLS.Enable = lo.ToPtr(conf.TLSEnable) out.Transport.TLS.DisableCustomTLSFirstByte = lo.ToPtr(conf.DisableCustomTLSFirstByte) out.Transport.TLS.TLSConfig.CertFile = conf.TLSCertFile out.Transport.TLS.TLSConfig.KeyFile = conf.TLSKeyFile out.Transport.TLS.TLSConfig.TrustedCaFile = conf.TLSTrustedCaFile out.Transport.TLS.TLSConfig.ServerName = conf.TLSServerName out.Log.To = conf.LogFile out.Log.Level = conf.LogLevel out.Log.MaxDays = conf.LogMaxDays out.Log.DisablePrintColor = conf.DisableLogColor out.WebServer.Addr = conf.AdminAddr out.WebServer.Port = conf.AdminPort out.WebServer.User = conf.AdminUser out.WebServer.Password = conf.AdminPwd out.WebServer.AssetsDir = conf.AssetsDir out.WebServer.PprofEnable = conf.PprofEnable out.DNSServer = conf.DNSServer out.LoginFailExit = lo.ToPtr(conf.LoginFailExit) out.Start = conf.Start out.UDPPacketSize = conf.UDPPacketSize out.Metadatas = conf.Metas out.IncludeConfigFiles = conf.IncludeConfigFiles return out } func Convert_ServerCommonConf_To_v1(conf *ServerCommonConf) *v1.ServerConfig { out := &v1.ServerConfig{} out.Auth.Method = v1.AuthMethod(conf.ServerConfig.AuthenticationMethod) out.Auth.Token = conf.ServerConfig.Token if conf.ServerConfig.AuthenticateHeartBeats { out.Auth.AdditionalScopes = append(out.Auth.AdditionalScopes, v1.AuthScopeHeartBeats) } if conf.ServerConfig.AuthenticateNewWorkConns { out.Auth.AdditionalScopes = append(out.Auth.AdditionalScopes, v1.AuthScopeNewWorkConns) } out.Auth.OIDC.Audience = conf.ServerConfig.OidcAudience out.Auth.OIDC.Issuer = conf.ServerConfig.OidcIssuer out.Auth.OIDC.SkipExpiryCheck = conf.ServerConfig.OidcSkipExpiryCheck out.Auth.OIDC.SkipIssuerCheck = conf.ServerConfig.OidcSkipIssuerCheck out.BindAddr = conf.BindAddr out.BindPort = conf.BindPort out.KCPBindPort = conf.KCPBindPort out.QUICBindPort = conf.QUICBindPort out.Transport.QUIC.KeepalivePeriod = conf.QUICKeepalivePeriod out.Transport.QUIC.MaxIdleTimeout = conf.QUICMaxIdleTimeout out.Transport.QUIC.MaxIncomingStreams = conf.QUICMaxIncomingStreams out.ProxyBindAddr = conf.ProxyBindAddr out.VhostHTTPPort = conf.VhostHTTPPort out.VhostHTTPSPort = conf.VhostHTTPSPort out.TCPMuxHTTPConnectPort = conf.TCPMuxHTTPConnectPort out.TCPMuxPassthrough = conf.TCPMuxPassthrough out.VhostHTTPTimeout = conf.VhostHTTPTimeout out.WebServer.Addr = conf.DashboardAddr out.WebServer.Port = conf.DashboardPort out.WebServer.User = conf.DashboardUser out.WebServer.Password = conf.DashboardPwd out.WebServer.AssetsDir = conf.AssetsDir if conf.DashboardTLSMode { out.WebServer.TLS = &v1.TLSConfig{} out.WebServer.TLS.CertFile = conf.DashboardTLSCertFile out.WebServer.TLS.KeyFile = conf.DashboardTLSKeyFile out.WebServer.PprofEnable = conf.PprofEnable } out.EnablePrometheus = conf.EnablePrometheus out.Log.To = conf.LogFile out.Log.Level = conf.LogLevel out.Log.MaxDays = conf.LogMaxDays out.Log.DisablePrintColor = conf.DisableLogColor out.DetailedErrorsToClient = lo.ToPtr(conf.DetailedErrorsToClient) out.SubDomainHost = conf.SubDomainHost out.Custom404Page = conf.Custom404Page out.UserConnTimeout = conf.UserConnTimeout out.UDPPacketSize = conf.UDPPacketSize out.NatHoleAnalysisDataReserveHours = conf.NatHoleAnalysisDataReserveHours out.Transport.TCPMux = lo.ToPtr(conf.TCPMux) out.Transport.TCPMuxKeepaliveInterval = conf.TCPMuxKeepaliveInterval out.Transport.TCPKeepAlive = conf.TCPKeepAlive out.Transport.MaxPoolCount = conf.MaxPoolCount out.Transport.HeartbeatTimeout = conf.HeartbeatTimeout out.Transport.TLS.Force = conf.TLSOnly out.Transport.TLS.CertFile = conf.TLSCertFile out.Transport.TLS.KeyFile = conf.TLSKeyFile out.Transport.TLS.TrustedCaFile = conf.TLSTrustedCaFile out.MaxPortsPerClient = conf.MaxPortsPerClient for _, v := range conf.HTTPPlugins { out.HTTPPlugins = append(out.HTTPPlugins, v1.HTTPPluginOptions{ Name: v.Name, Addr: v.Addr, Path: v.Path, Ops: v.Ops, TLSVerify: v.TLSVerify, }) } out.AllowPorts, _ = types.NewPortsRangeSliceFromString(conf.AllowPortsStr) return out } func transformHeadersFromPluginParams(params map[string]string) v1.HeaderOperations { out := v1.HeaderOperations{} for k, v := range params { if !strings.HasPrefix(k, "plugin_header_") { continue } if k = strings.TrimPrefix(k, "plugin_header_"); k != "" { if out.Set == nil { out.Set = make(map[string]string) } out.Set[k] = v } } return out } func Convert_ProxyConf_To_v1_Base(conf ProxyConf) *v1.ProxyBaseConfig { out := &v1.ProxyBaseConfig{} base := conf.GetBaseConfig() out.Name = base.ProxyName out.Type = base.ProxyType out.Metadatas = base.Metas out.Transport.UseEncryption = base.UseEncryption out.Transport.UseCompression = base.UseCompression out.Transport.BandwidthLimit = base.BandwidthLimit out.Transport.BandwidthLimitMode = base.BandwidthLimitMode out.Transport.ProxyProtocolVersion = base.ProxyProtocolVersion out.LoadBalancer.Group = base.Group out.LoadBalancer.GroupKey = base.GroupKey out.HealthCheck.Type = base.HealthCheckType out.HealthCheck.TimeoutSeconds = base.HealthCheckTimeoutS out.HealthCheck.MaxFailed = base.HealthCheckMaxFailed out.HealthCheck.IntervalSeconds = base.HealthCheckIntervalS out.HealthCheck.Path = base.HealthCheckURL out.LocalIP = base.LocalIP out.LocalPort = base.LocalPort switch base.Plugin { case "http2https": out.Plugin.ClientPluginOptions = &v1.HTTP2HTTPSPluginOptions{ LocalAddr: base.PluginParams["plugin_local_addr"], HostHeaderRewrite: base.PluginParams["plugin_host_header_rewrite"], RequestHeaders: transformHeadersFromPluginParams(base.PluginParams), } case "http_proxy": out.Plugin.ClientPluginOptions = &v1.HTTPProxyPluginOptions{ HTTPUser: base.PluginParams["plugin_http_user"], HTTPPassword: base.PluginParams["plugin_http_passwd"], } case "https2http": out.Plugin.ClientPluginOptions = &v1.HTTPS2HTTPPluginOptions{ LocalAddr: base.PluginParams["plugin_local_addr"], HostHeaderRewrite: base.PluginParams["plugin_host_header_rewrite"], RequestHeaders: transformHeadersFromPluginParams(base.PluginParams), CrtPath: base.PluginParams["plugin_crt_path"], KeyPath: base.PluginParams["plugin_key_path"], } case "https2https": out.Plugin.ClientPluginOptions = &v1.HTTPS2HTTPSPluginOptions{ LocalAddr: base.PluginParams["plugin_local_addr"], HostHeaderRewrite: base.PluginParams["plugin_host_header_rewrite"], RequestHeaders: transformHeadersFromPluginParams(base.PluginParams), CrtPath: base.PluginParams["plugin_crt_path"], KeyPath: base.PluginParams["plugin_key_path"], } case "socks5": out.Plugin.ClientPluginOptions = &v1.Socks5PluginOptions{ Username: base.PluginParams["plugin_user"], Password: base.PluginParams["plugin_passwd"], } case "static_file": out.Plugin.ClientPluginOptions = &v1.StaticFilePluginOptions{ LocalPath: base.PluginParams["plugin_local_path"], StripPrefix: base.PluginParams["plugin_strip_prefix"], HTTPUser: base.PluginParams["plugin_http_user"], HTTPPassword: base.PluginParams["plugin_http_passwd"], } case "unix_domain_socket": out.Plugin.ClientPluginOptions = &v1.UnixDomainSocketPluginOptions{ UnixPath: base.PluginParams["plugin_unix_path"], } } out.Plugin.Type = base.Plugin return out } func Convert_ProxyConf_To_v1(conf ProxyConf) v1.ProxyConfigurer { outBase := Convert_ProxyConf_To_v1_Base(conf) var out v1.ProxyConfigurer switch v := conf.(type) { case *TCPProxyConf: c := &v1.TCPProxyConfig{ProxyBaseConfig: *outBase} c.RemotePort = v.RemotePort out = c case *UDPProxyConf: c := &v1.UDPProxyConfig{ProxyBaseConfig: *outBase} c.RemotePort = v.RemotePort out = c case *HTTPProxyConf: c := &v1.HTTPProxyConfig{ProxyBaseConfig: *outBase} c.CustomDomains = v.CustomDomains c.SubDomain = v.SubDomain c.Locations = v.Locations c.HTTPUser = v.HTTPUser c.HTTPPassword = v.HTTPPwd c.HostHeaderRewrite = v.HostHeaderRewrite c.RequestHeaders.Set = v.Headers c.RouteByHTTPUser = v.RouteByHTTPUser out = c case *HTTPSProxyConf: c := &v1.HTTPSProxyConfig{ProxyBaseConfig: *outBase} c.CustomDomains = v.CustomDomains c.SubDomain = v.SubDomain out = c case *TCPMuxProxyConf: c := &v1.TCPMuxProxyConfig{ProxyBaseConfig: *outBase} c.CustomDomains = v.CustomDomains c.SubDomain = v.SubDomain c.HTTPUser = v.HTTPUser c.HTTPPassword = v.HTTPPwd c.RouteByHTTPUser = v.RouteByHTTPUser c.Multiplexer = v.Multiplexer out = c case *STCPProxyConf: c := &v1.STCPProxyConfig{ProxyBaseConfig: *outBase} c.Secretkey = v.Sk c.AllowUsers = v.AllowUsers out = c case *SUDPProxyConf: c := &v1.SUDPProxyConfig{ProxyBaseConfig: *outBase} c.Secretkey = v.Sk c.AllowUsers = v.AllowUsers out = c case *XTCPProxyConf: c := &v1.XTCPProxyConfig{ProxyBaseConfig: *outBase} c.Secretkey = v.Sk c.AllowUsers = v.AllowUsers out = c } return out } func Convert_VisitorConf_To_v1_Base(conf VisitorConf) *v1.VisitorBaseConfig { out := &v1.VisitorBaseConfig{} base := conf.GetBaseConfig() out.Name = base.ProxyName out.Type = base.ProxyType out.Transport.UseEncryption = base.UseEncryption out.Transport.UseCompression = base.UseCompression out.SecretKey = base.Sk out.ServerUser = base.ServerUser out.ServerName = base.ServerName out.BindAddr = base.BindAddr out.BindPort = base.BindPort return out } func Convert_VisitorConf_To_v1(conf VisitorConf) v1.VisitorConfigurer { outBase := Convert_VisitorConf_To_v1_Base(conf) var out v1.VisitorConfigurer switch v := conf.(type) { case *STCPVisitorConf: c := &v1.STCPVisitorConfig{VisitorBaseConfig: *outBase} out = c case *SUDPVisitorConf: c := &v1.SUDPVisitorConfig{VisitorBaseConfig: *outBase} out = c case *XTCPVisitorConf: c := &v1.XTCPVisitorConfig{VisitorBaseConfig: *outBase} c.Protocol = v.Protocol c.KeepTunnelOpen = v.KeepTunnelOpen c.MaxRetriesAnHour = v.MaxRetriesAnHour c.MinRetryInterval = v.MinRetryInterval c.FallbackTo = v.FallbackTo c.FallbackTimeoutMs = v.FallbackTimeoutMs out = c } return out }