diff --git a/client/service.go b/client/service.go index 266ab49..9f86ec7 100644 --- a/client/service.go +++ b/client/service.go @@ -34,6 +34,7 @@ import ( fmux "github.com/hashicorp/yamux" ) +// Service is a client service. type Service struct { // uniq id got from frps, attach it in loginMsg runId string @@ -58,6 +59,7 @@ type Service struct { closedCh chan int } +// NewService creates a new client service with the given configuration. func NewService(cfg config.ClientCommonConf, pxyCfgs map[string]config.ProxyConf, visitorCfgs map[string]config.VisitorConf, cfgFile string) (svr *Service, err error) { svr = &Service{ cfg: cfg, diff --git a/models/config/client_common.go b/models/config/client_common.go index 5d9d127..fe87e08 100644 --- a/models/config/client_common.go +++ b/models/config/client_common.go @@ -23,34 +23,101 @@ import ( ini "github.com/vaughan0/go-ini" ) -// client common config +// ClientCommonConf contains information for a client service. It is +// recommended to use GetDefaultClientConf instead of creating this object +// directly, so that all unspecified fields have reasonable default values. type ClientCommonConf struct { - ServerAddr string `json:"server_addr"` - ServerPort int `json:"server_port"` - HttpProxy string `json:"http_proxy"` - LogFile string `json:"log_file"` - LogWay string `json:"log_way"` - LogLevel string `json:"log_level"` - LogMaxDays int64 `json:"log_max_days"` - DisableLogColor bool `json:"disable_log_color"` - Token string `json:"token"` - AdminAddr string `json:"admin_addr"` - AdminPort int `json:"admin_port"` - AdminUser string `json:"admin_user"` - AdminPwd string `json:"admin_pwd"` - AssetsDir string `json:"assets_dir"` - PoolCount int `json:"pool_count"` - TcpMux bool `json:"tcp_mux"` - User string `json:"user"` - DnsServer string `json:"dns_server"` - LoginFailExit bool `json:"login_fail_exit"` - Start map[string]struct{} `json:"start"` - Protocol string `json:"protocol"` - TLSEnable bool `json:"tls_enable"` - HeartBeatInterval int64 `json:"heartbeat_interval"` - HeartBeatTimeout int64 `json:"heartbeat_timeout"` + // ServerAddr specifies the address of the server to connect to. By + // default, this value is "0.0.0.0". + ServerAddr string `json:"server_addr"` + // ServerPort specifies the port to connect to the server on. By default, + // this value is 7000. + ServerPort int `json:"server_port"` + // HttpProxy specifies a proxy address to connect to the server through. If + // this value is "", the server will be connected to directly. By default, + // this value is read from the "http_proxy" environment variable. + HttpProxy string `json:"http_proxy"` + // LogFile specifies a file where logs will be written to. This value will + // only be used if LogWay is set appropriately. By default, this value is + // "console". + LogFile string `json:"log_file"` + // LogWay specifies the way logging is managed. Valid values are "console" + // or "file". If "console" is used, logs will be printed to stdout. If + // "file" is used, logs will be printed to LogFile. By default, this value + // is "console". + LogWay string `json:"log_way"` + // LogLevel specifies the minimum log level. Valid values are "trace", + // "debug", "info", "warn", and "error". By default, this value is "info". + LogLevel string `json:"log_level"` + // LogMaxDays specifies the maximum number of days to store log information + // before deletion. This is only used if LogWay == "file". By default, this + // value is 0. + LogMaxDays int64 `json:"log_max_days"` + // DisableLogColor disables log colors when LogWay == "console" when set to + // true. By default, this value is false. + DisableLogColor bool `json:"disable_log_color"` + // Token specifies the authorization token used to create keys to be sent + // to the server. The server must have a matching token for authorization + // to succeed. By default, this value is "". + Token string `json:"token"` + // AdminAddr specifies the address that the admin server binds to. By + // default, this value is "127.0.0.1". + AdminAddr string `json:"admin_addr"` + // AdminPort specifies the port for the admin server to listen on. If this + // value is 0, the admin server will not be started. By default, this value + // is 0. + AdminPort int `json:"admin_port"` + // AdminUser specifies the username that the admin server will use for + // login. By default, this value is "admin". + AdminUser string `json:"admin_user"` + // AdminPwd specifies the password that the admin server will use for + // login. By default, this value is "admin". + AdminPwd string `json:"admin_pwd"` + // AssetsDir specifies the local directory that the admin server will load + // resources from. If this value is "", assets will be loaded from the + // bundled executable using statik. By default, this value is "". + AssetsDir string `json:"assets_dir"` + // PoolCount specifies the number of connections the client will make to + // the server in advance. By default, this value is 0. + PoolCount int `json:"pool_count"` + // TcpMux toggles TCP stream multiplexing. This allows multiple requests + // from a client to share a single TCP connection. If this value is true, + // the server must have TCP multiplexing enabled as well. By default, this + // value is true. + TcpMux bool `json:"tcp_mux"` + // User specifies a prefix for proxy names to distinguish them from other + // clients. If this value is not "", proxy names will automatically be + // changed to "{user}.{proxy_name}". By default, this value is "". + User string `json:"user"` + // DnsServer specifies a DNS server address for FRPC to use. If this value + // is "", the default DNS will be used. By default, this value is "". + DnsServer string `json:"dns_server"` + // LoginFailExit controls whether or not the client should exit after a + // failed login attempt. If false, the client will retry until a login + // attempt succeeds. By default, this value is true. + LoginFailExit bool `json:"login_fail_exit"` + // Start specifies a set of enabled proxies by name. If this set is empty, + // all supplied proxies are enabled. By default, this value is an empty + // set. + Start map[string]struct{} `json:"start"` + // Protocol specifies the protocol to use when interacting with the server. + // Valid values are "tcp", "kcp", and "websocket". By default, this value + // is "tcp". + Protocol string `json:"protocol"` + // TLSEnable specifies whether or not TLS should be used when communicating + // with the server. + TLSEnable bool `json:"tls_enable"` + // HeartBeatInterval specifies at what interval heartbeats are sent to the + // server, in seconds. It is not recommended to change this value. By + // default, this value is 30. + HeartBeatInterval int64 `json:"heartbeat_interval"` + // HeartBeatTimeout specifies the maximum allowed heartbeat response delay + // before the connection is terminated, in seconds. It is not recommended + // to change this value. By default, this value is 90. + HeartBeatTimeout int64 `json:"heartbeat_timeout"` } +// GetDefaultClientConf returns a client configuration with default values. func GetDefaultClientConf() ClientCommonConf { return ClientCommonConf{ ServerAddr: "0.0.0.0", @@ -85,8 +152,7 @@ func UnmarshalClientConfFromIni(content string) (cfg ClientCommonConf, err error conf, err := ini.Load(strings.NewReader(content)) if err != nil { - err = fmt.Errorf("parse ini conf file error: %v", err) - return ClientCommonConf{}, err + return ClientCommonConf{}, fmt.Errorf("parse ini conf file error: %v", err) } var ( diff --git a/models/config/proxy.go b/models/config/proxy.go index 758d563..9ab1ef8 100644 --- a/models/config/proxy.go +++ b/models/config/proxy.go @@ -97,17 +97,33 @@ func NewProxyConfFromIni(prefix string, name string, section ini.Section) (cfg P return } -// BaseProxy info +// BaseProxyConf provides configuration info that is common to all proxy types. type BaseProxyConf struct { + // ProxyName is the name of this proxy. ProxyName string `json:"proxy_name"` + // ProxyType specifies the type of this proxy. Valid values include "tcp", + // "udp", "http", "https", "stcp", and "xtcp". By default, this value is + // "tcp". ProxyType string `json:"proxy_type"` - UseEncryption bool `json:"use_encryption"` - UseCompression bool `json:"use_compression"` - Group string `json:"group"` - GroupKey string `json:"group_key"` + // UseEncryption controls whether or not communication with the server will + // be encrypted. Encryption is done using the tokens supplied in the server + // and client configuration. By default, this value is false. + UseEncryption bool `json:"use_encryption"` + // UseCompression controls whether or not communication with the server + // will be compressed. By default, this value is false. + UseCompression bool `json:"use_compression"` + // Group specifies which group the proxy is a part of. The server will use + // this information to load balance proxies in the same group. If the value + // is "", this proxy will not be in a group. By default, this value is "". + Group string `json:"group"` + // GroupKey specifies a group key, which should be the same among proxies + // of the same group. By default, this value is "". + GroupKey string `json:"group_key"` - // only used for client + // ProxyProtocolVersion specifies which protocol version to use. Valid + // values include "v1", "v2", and "". If the value is "", a protocol + // version will be automatically selected. By default, this value is "". ProxyProtocolVersion string `json:"proxy_protocol_version"` LocalSvrConf HealthCheckConf @@ -332,12 +348,20 @@ func (cfg *DomainConf) checkForSvr(serverCfg ServerCommonConf) (err error) { return } -// Local service info +// LocalSvrConf configures what location the client will proxy to, or what +// plugin will be used. type LocalSvrConf struct { - LocalIp string `json:"local_ip"` - LocalPort int `json:"local_port"` + // LocalIp specifies the IP address or host name to proxy to. + LocalIp string `json:"local_ip"` + // LocalPort specifies the port to proxy to. + LocalPort int `json:"local_port"` - Plugin string `json:"plugin"` + // Plugin specifies what plugin should be used for proxying. If this value + // is set, the LocalIp and LocalPort values will be ignored. By default, + // this value is "". + Plugin string `json:"plugin"` + // PluginParams specify parameters to be passed to the plugin, if one is + // being used. By default, this value is an empty map. PluginParams map[string]string `json:"plugin_params"` } @@ -399,15 +423,35 @@ func (cfg *LocalSvrConf) checkForCli() (err error) { return } -// Health check info +// HealthCheckConf configures health checking. This can be useful for load +// balancing purposes to detect and remove proxies to failing services. type HealthCheckConf struct { - HealthCheckType string `json:"health_check_type"` // tcp | http - HealthCheckTimeoutS int `json:"health_check_timeout_s"` - HealthCheckMaxFailed int `json:"health_check_max_failed"` - HealthCheckIntervalS int `json:"health_check_interval_s"` - HealthCheckUrl string `json:"health_check_url"` - - // local_ip + local_port + // HealthCheckType specifies what protocol to use for health checking. + // Valid values include "tcp", "http", and "". If this value is "", health + // checking will not be performed. By default, this value is "". + // + // If the type is "tcp", a connection will be attempted to the target + // server. If a connection cannot be established, the health check fails. + // + // If the type is "http", a GET request will be made to the endpoint + // specified by HealthCheckUrl. If the response is not a 200, the health + // check fails. + HealthCheckType string `json:"health_check_type"` // tcp | http + // HealthCheckTimeoutS specifies the number of seconds to wait for a health + // check attempt to connect. If the timeout is reached, this counts as a + // health check failure. By default, this value is 3. + HealthCheckTimeoutS int `json:"health_check_timeout_s"` + // HealthCheckMaxFailed specifies the number of allowed failures before the + // proxy is stopped. By default, this value is 1. + HealthCheckMaxFailed int `json:"health_check_max_failed"` + // HealthCheckIntervalS specifies the time in seconds between health + // checks. By default, this value is 10. + HealthCheckIntervalS int `json:"health_check_interval_s"` + // HealthCheckUrl specifies the address to send health checks to if the + // health check type is "http". + HealthCheckUrl string `json:"health_check_url"` + // HealthCheckAddr specifies the address to connect to if the health check + // type is "tcp". HealthCheckAddr string `json:"-"` } diff --git a/models/config/server_common.go b/models/config/server_common.go index 8a486fb..a190a61 100644 --- a/models/config/server_common.go +++ b/models/config/server_common.go @@ -24,46 +24,120 @@ import ( "github.com/fatedier/frp/utils/util" ) -// common config +// ServerCommonConf contains information for a server service. It is +// recommended to use GetDefaultServerConf instead of creating this object +// directly, so that all unspecified fields have reasonable default values. type ServerCommonConf struct { - BindAddr string `json:"bind_addr"` - BindPort int `json:"bind_port"` - BindUdpPort int `json:"bind_udp_port"` - KcpBindPort int `json:"kcp_bind_port"` + // BindAddr specifies the address that the server binds to. By default, + // this value is "0.0.0.0". + BindAddr string `json:"bind_addr"` + // BindPort specifies the port that the server listens on. By default, this + // value is 7000. + BindPort int `json:"bind_port"` + // BindUdpPort specifies the UDP port that the server listens on. If this + // value is 0, the server will not listen for UDP connections. By default, + // this value is 0 + BindUdpPort int `json:"bind_udp_port"` + // BindKcpPort specifies the KCP port that the server listens on. If this + // value is 0, the server will not listen for KCP connections. By default, + // this value is 0. + KcpBindPort int `json:"kcp_bind_port"` + // ProxyBindAddr specifies the address that the proxy binds to. This value + // may be the same as BindAddr. By default, this value is "0.0.0.0". ProxyBindAddr string `json:"proxy_bind_addr"` - // If VhostHttpPort equals 0, don't listen a public port for http protocol. + // VhostHttpPort specifies the port that the server listens for HTTP Vhost + // requests. If this value is 0, the server will not listen for HTTP + // requests. By default, this value is 0. VhostHttpPort int `json:"vhost_http_port"` - // if VhostHttpsPort equals 0, don't listen a public port for https protocol + // VhostHttpsPort specifies the port that the server listens for HTTPS + // Vhost requests. If this value is 0, the server will not listen for HTTPS + // requests. By default, this value is 0. VhostHttpsPort int `json:"vhost_https_port"` + // VhostHttpTimeout specifies the response header timeout for the Vhost + // HTTP server, in seconds. By default, this value is 60. VhostHttpTimeout int64 `json:"vhost_http_timeout"` + // DashboardAddr specifies the address that the dashboard binds to. By + // default, this value is "0.0.0.0". DashboardAddr string `json:"dashboard_addr"` - // if DashboardPort equals 0, dashboard is not available - DashboardPort int `json:"dashboard_port"` - DashboardUser string `json:"dashboard_user"` - DashboardPwd string `json:"dashboard_pwd"` - AssetsDir string `json:"asserts_dir"` - LogFile string `json:"log_file"` - LogWay string `json:"log_way"` // console or file - LogLevel string `json:"log_level"` - LogMaxDays int64 `json:"log_max_days"` - DisableLogColor bool `json:"disable_log_color"` - Token string `json:"token"` - SubDomainHost string `json:"subdomain_host"` - TcpMux bool `json:"tcp_mux"` - Custom404Page string `json:"custom_404_page"` + // DashboardPort specifies the port that the dashboard listens on. If this + // value is 0, the dashboard will not be started. By default, this value is + // 0. + DashboardPort int `json:"dashboard_port"` + // DashboardUser specifies the username that the dashboard will use for + // login. By default, this value is "admin". + DashboardUser string `json:"dashboard_user"` + // DashboardUser specifies the password that the dashboard will use for + // login. By default, this value is "admin". + DashboardPwd string `json:"dashboard_pwd"` + // AssetsDir specifies the local directory that the dashboard will load + // resources from. If this value is "", assets will be loaded from the + // bundled executable using statik. By default, this value is "". + AssetsDir string `json:"asserts_dir"` + // LogFile specifies a file where logs will be written to. This value will + // only be used if LogWay is set appropriately. By default, this value is + // "console". + LogFile string `json:"log_file"` + // LogWay specifies the way logging is managed. Valid values are "console" + // or "file". If "console" is used, logs will be printed to stdout. If + // "file" is used, logs will be printed to LogFile. By default, this value + // is "console". + LogWay string `json:"log_way"` + // LogLevel specifies the minimum log level. Valid values are "trace", + // "debug", "info", "warn", and "error". By default, this value is "info". + LogLevel string `json:"log_level"` + // LogMaxDays specifies the maximum number of days to store log information + // before deletion. This is only used if LogWay == "file". By default, this + // value is 0. + LogMaxDays int64 `json:"log_max_days"` + // DisableLogColor disables log colors when LogWay == "console" when set to + // true. By default, this value is false. + DisableLogColor bool `json:"disable_log_color"` + // Token specifies the authorization token used to authenticate keys + // received from clients. Clients must have a matching token to be + // authorized to use the server. By default, this value is "". + Token string `json:"token"` + // SubDomainHost specifies the domain that will be attached to sub-domains + // requested by the client when using Vhost proxying. For example, if this + // value is set to "frps.com" and the client requested the subdomain + // "test", the resulting URL would be "test.frps.com". By default, this + // value is "". + SubDomainHost string `json:"subdomain_host"` + // TcpMux toggles TCP stream multiplexing. This allows multiple requests + // from a client to share a single TCP connection. By default, this value + // is true. + TcpMux bool `json:"tcp_mux"` + // Custom404Page specifies a path to a custom 404 page to display. If this + // value is "", a default page will be displayed. By default, this value is + // "". + Custom404Page string `json:"custom_404_page"` - AllowPorts map[int]struct{} - MaxPoolCount int64 `json:"max_pool_count"` + // AllowPorts specifies a set of ports that clients are able to proxy to. + // If the length of this value is 0, all ports are allowed. By default, + // this value is an empty set. + AllowPorts map[int]struct{} + // MaxPoolCount specifies the maximum pool size for each proxy. By default, + // this value is 5. + MaxPoolCount int64 `json:"max_pool_count"` + // MaxPortsPerClient specifies the maximum number of ports a single client + // may proxy to. If this value is 0, no limit will be applied. By default, + // this value is 0. MaxPortsPerClient int64 `json:"max_ports_per_client"` - HeartBeatTimeout int64 `json:"heart_beat_timeout"` - UserConnTimeout int64 `json:"user_conn_timeout"` + // HeartBeatTimeout specifies the maximum time to wait for a heartbeat + // before terminating the connection. It is not recommended to change this + // value. By default, this value is 90. + HeartBeatTimeout int64 `json:"heart_beat_timeout"` + // UserConnTimeout specifies the maximum time to wait for a work + // connection. By default, this value is 10. + UserConnTimeout int64 `json:"user_conn_timeout"` } +// GetDefaultServerConf returns a server configuration with reasonable +// defaults. func GetDefaultServerConf() ServerCommonConf { return ServerCommonConf{ BindAddr: "0.0.0.0", @@ -96,6 +170,8 @@ func GetDefaultServerConf() ServerCommonConf { } } +// UnmarshalServerConfFromIni parses the contents of a server configuration ini +// file and returns the resulting server configuration. func UnmarshalServerConfFromIni(content string) (cfg ServerCommonConf, err error) { cfg = GetDefaultServerConf()