2017-03-08 19:03:47 +01:00
|
|
|
// Copyright 2016 fatedier, fatedier@gmail.com
|
|
|
|
//
|
|
|
|
// 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 config
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
ini "github.com/vaughan0/go-ini"
|
2018-01-25 16:05:07 +01:00
|
|
|
|
|
|
|
"github.com/fatedier/frp/utils/util"
|
2017-03-08 19:03:47 +01:00
|
|
|
)
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
var (
|
|
|
|
// server global configure used for generate proxy conf used in frps
|
|
|
|
proxyBindAddr string
|
|
|
|
subDomainHost string
|
|
|
|
vhostHttpPort int
|
|
|
|
vhostHttpsPort int
|
|
|
|
)
|
|
|
|
|
|
|
|
func InitServerCfg(cfg *ServerCommonConf) {
|
|
|
|
proxyBindAddr = cfg.ProxyBindAddr
|
|
|
|
subDomainHost = cfg.SubDomainHost
|
|
|
|
vhostHttpPort = cfg.VhostHttpPort
|
|
|
|
vhostHttpsPort = cfg.VhostHttpsPort
|
|
|
|
}
|
2017-03-08 19:03:47 +01:00
|
|
|
|
|
|
|
// common config
|
|
|
|
type ServerCommonConf struct {
|
2018-04-10 11:46:49 +02:00
|
|
|
BindAddr string `json:"bind_addr"`
|
|
|
|
BindPort int `json:"bind_port"`
|
|
|
|
BindUdpPort int `json:"bind_udp_port"`
|
|
|
|
KcpBindPort int `json:"kcp_bind_port"`
|
|
|
|
ProxyBindAddr string `json:"proxy_bind_addr"`
|
2017-03-08 19:03:47 +01:00
|
|
|
|
|
|
|
// If VhostHttpPort equals 0, don't listen a public port for http protocol.
|
2018-04-10 11:46:49 +02:00
|
|
|
VhostHttpPort int `json:"vhost_http_port"`
|
2017-03-08 19:03:47 +01:00
|
|
|
|
|
|
|
// if VhostHttpsPort equals 0, don't listen a public port for https protocol
|
2019-01-31 09:49:23 +01:00
|
|
|
VhostHttpsPort int `json:"vhost_https_port"`
|
2018-08-08 05:18:38 +02:00
|
|
|
|
|
|
|
VhostHttpTimeout int64 `json:"vhost_http_timeout"`
|
|
|
|
|
|
|
|
DashboardAddr string `json:"dashboard_addr"`
|
2017-03-08 19:03:47 +01:00
|
|
|
|
|
|
|
// if DashboardPort equals 0, dashboard is not available
|
2018-04-10 11:46:49 +02:00
|
|
|
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"`
|
|
|
|
Token string `json:"token"`
|
|
|
|
SubDomainHost string `json:"subdomain_host"`
|
|
|
|
TcpMux bool `json:"tcp_mux"`
|
2017-03-08 19:03:47 +01:00
|
|
|
|
2018-04-23 19:26:05 +02:00
|
|
|
AllowPorts map[int]struct{}
|
|
|
|
MaxPoolCount int64 `json:"max_pool_count"`
|
|
|
|
MaxPortsPerClient int64 `json:"max_ports_per_client"`
|
|
|
|
HeartBeatTimeout int64 `json:"heart_beat_timeout"`
|
|
|
|
UserConnTimeout int64 `json:"user_conn_timeout"`
|
2017-03-08 19:03:47 +01:00
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
func GetDefaultServerConf() *ServerCommonConf {
|
2017-03-08 19:03:47 +01:00
|
|
|
return &ServerCommonConf{
|
2018-04-23 19:26:05 +02:00
|
|
|
BindAddr: "0.0.0.0",
|
|
|
|
BindPort: 7000,
|
|
|
|
BindUdpPort: 0,
|
|
|
|
KcpBindPort: 0,
|
|
|
|
ProxyBindAddr: "0.0.0.0",
|
|
|
|
VhostHttpPort: 0,
|
|
|
|
VhostHttpsPort: 0,
|
2018-08-08 05:18:38 +02:00
|
|
|
VhostHttpTimeout: 60,
|
2018-04-23 19:26:05 +02:00
|
|
|
DashboardAddr: "0.0.0.0",
|
|
|
|
DashboardPort: 0,
|
|
|
|
DashboardUser: "admin",
|
|
|
|
DashboardPwd: "admin",
|
|
|
|
AssetsDir: "",
|
|
|
|
LogFile: "console",
|
|
|
|
LogWay: "console",
|
|
|
|
LogLevel: "info",
|
|
|
|
LogMaxDays: 3,
|
|
|
|
Token: "",
|
|
|
|
SubDomainHost: "",
|
|
|
|
TcpMux: true,
|
|
|
|
AllowPorts: make(map[int]struct{}),
|
|
|
|
MaxPoolCount: 5,
|
|
|
|
MaxPortsPerClient: 0,
|
|
|
|
HeartBeatTimeout: 90,
|
|
|
|
UserConnTimeout: 10,
|
2017-03-08 19:03:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
func UnmarshalServerConfFromIni(defaultCfg *ServerCommonConf, content string) (cfg *ServerCommonConf, err error) {
|
|
|
|
cfg = defaultCfg
|
|
|
|
if cfg == nil {
|
|
|
|
cfg = GetDefaultServerConf()
|
|
|
|
}
|
|
|
|
|
|
|
|
conf, err := ini.Load(strings.NewReader(content))
|
|
|
|
if err != nil {
|
|
|
|
err = fmt.Errorf("parse ini conf file error: %v", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-03-08 19:03:47 +01:00
|
|
|
var (
|
|
|
|
tmpStr string
|
|
|
|
ok bool
|
|
|
|
v int64
|
|
|
|
)
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "bind_addr"); ok {
|
2017-03-08 19:03:47 +01:00
|
|
|
cfg.BindAddr = tmpStr
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "bind_port"); ok {
|
2018-01-17 14:49:37 +01:00
|
|
|
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
|
|
|
|
err = fmt.Errorf("Parse conf error: invalid bind_port")
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
cfg.BindPort = int(v)
|
2017-03-08 19:03:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "bind_udp_port"); ok {
|
2018-01-17 14:49:37 +01:00
|
|
|
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
|
|
|
|
err = fmt.Errorf("Parse conf error: invalid bind_udp_port")
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
cfg.BindUdpPort = int(v)
|
2017-10-24 12:20:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "kcp_bind_port"); ok {
|
2018-01-17 14:49:37 +01:00
|
|
|
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
|
|
|
|
err = fmt.Errorf("Parse conf error: invalid kcp_bind_port")
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
cfg.KcpBindPort = int(v)
|
2017-06-13 17:36:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "proxy_bind_addr"); ok {
|
2017-07-04 19:40:01 +02:00
|
|
|
cfg.ProxyBindAddr = tmpStr
|
|
|
|
} else {
|
|
|
|
cfg.ProxyBindAddr = cfg.BindAddr
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "vhost_http_port"); ok {
|
2018-01-17 14:49:37 +01:00
|
|
|
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
|
|
|
|
err = fmt.Errorf("Parse conf error: invalid vhost_http_port")
|
2017-03-08 19:03:47 +01:00
|
|
|
return
|
2018-01-17 14:49:37 +01:00
|
|
|
} else {
|
|
|
|
cfg.VhostHttpPort = int(v)
|
2017-03-08 19:03:47 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cfg.VhostHttpPort = 0
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "vhost_https_port"); ok {
|
2018-01-17 14:49:37 +01:00
|
|
|
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
|
|
|
|
err = fmt.Errorf("Parse conf error: invalid vhost_https_port")
|
2017-03-08 19:03:47 +01:00
|
|
|
return
|
2018-01-17 14:49:37 +01:00
|
|
|
} else {
|
|
|
|
cfg.VhostHttpsPort = int(v)
|
2017-03-08 19:03:47 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cfg.VhostHttpsPort = 0
|
|
|
|
}
|
|
|
|
|
2018-08-08 05:18:38 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "vhost_http_timeout"); ok {
|
|
|
|
v, errRet := strconv.ParseInt(tmpStr, 10, 64)
|
|
|
|
if errRet != nil || v < 0 {
|
|
|
|
err = fmt.Errorf("Parse conf error: invalid vhost_http_timeout")
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
cfg.VhostHttpTimeout = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "dashboard_addr"); ok {
|
2017-11-28 08:56:34 +01:00
|
|
|
cfg.DashboardAddr = tmpStr
|
|
|
|
} else {
|
|
|
|
cfg.DashboardAddr = cfg.BindAddr
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "dashboard_port"); ok {
|
2018-01-17 14:49:37 +01:00
|
|
|
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
|
|
|
|
err = fmt.Errorf("Parse conf error: invalid dashboard_port")
|
2017-03-08 19:03:47 +01:00
|
|
|
return
|
2018-01-17 14:49:37 +01:00
|
|
|
} else {
|
|
|
|
cfg.DashboardPort = int(v)
|
2017-03-08 19:03:47 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cfg.DashboardPort = 0
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "dashboard_user"); ok {
|
2017-03-08 19:03:47 +01:00
|
|
|
cfg.DashboardUser = tmpStr
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "dashboard_pwd"); ok {
|
2017-03-08 19:03:47 +01:00
|
|
|
cfg.DashboardPwd = tmpStr
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "assets_dir"); ok {
|
2017-03-08 19:03:47 +01:00
|
|
|
cfg.AssetsDir = tmpStr
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "log_file"); ok {
|
2017-03-08 19:03:47 +01:00
|
|
|
cfg.LogFile = tmpStr
|
|
|
|
if cfg.LogFile == "console" {
|
|
|
|
cfg.LogWay = "console"
|
|
|
|
} else {
|
|
|
|
cfg.LogWay = "file"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "log_level"); ok {
|
2017-03-08 19:03:47 +01:00
|
|
|
cfg.LogLevel = tmpStr
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "log_max_days"); ok {
|
2017-03-08 19:03:47 +01:00
|
|
|
v, err = strconv.ParseInt(tmpStr, 10, 64)
|
|
|
|
if err == nil {
|
|
|
|
cfg.LogMaxDays = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
cfg.Token, _ = conf.Get("common", "token")
|
2017-03-08 19:03:47 +01:00
|
|
|
|
2018-04-23 19:26:05 +02:00
|
|
|
if allowPortsStr, ok := conf.Get("common", "allow_ports"); ok {
|
2018-04-10 11:46:49 +02:00
|
|
|
// e.g. 1000-2000,2001,2002,3000-4000
|
|
|
|
ports, errRet := util.ParseRangeNumbers(allowPortsStr)
|
|
|
|
if errRet != nil {
|
2018-04-23 19:26:05 +02:00
|
|
|
err = fmt.Errorf("Parse conf error: allow_ports: %v", errRet)
|
2018-04-10 11:46:49 +02:00
|
|
|
return
|
|
|
|
}
|
2018-01-25 16:05:07 +01:00
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
for _, port := range ports {
|
2018-04-23 19:26:05 +02:00
|
|
|
cfg.AllowPorts[int(port)] = struct{}{}
|
2017-03-08 19:03:47 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "max_pool_count"); ok {
|
2018-01-26 07:56:55 +01:00
|
|
|
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
|
|
|
|
err = fmt.Errorf("Parse conf error: invalid max_pool_count")
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
if v < 0 {
|
|
|
|
err = fmt.Errorf("Parse conf error: invalid max_pool_count")
|
|
|
|
return
|
|
|
|
}
|
2017-03-08 19:03:47 +01:00
|
|
|
cfg.MaxPoolCount = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "max_ports_per_client"); ok {
|
2018-01-26 07:56:55 +01:00
|
|
|
if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
|
|
|
|
err = fmt.Errorf("Parse conf error: invalid max_ports_per_client")
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
if v < 0 {
|
|
|
|
err = fmt.Errorf("Parse conf error: invalid max_ports_per_client")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
cfg.MaxPortsPerClient = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "subdomain_host"); ok {
|
2017-03-08 19:03:47 +01:00
|
|
|
cfg.SubDomainHost = strings.ToLower(strings.TrimSpace(tmpStr))
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "tcp_mux"); ok && tmpStr == "false" {
|
2017-05-17 11:47:20 +02:00
|
|
|
cfg.TcpMux = false
|
|
|
|
} else {
|
|
|
|
cfg.TcpMux = true
|
|
|
|
}
|
|
|
|
|
2018-04-10 11:46:49 +02:00
|
|
|
if tmpStr, ok = conf.Get("common", "heartbeat_timeout"); ok {
|
2017-03-08 19:03:47 +01:00
|
|
|
v, errRet := strconv.ParseInt(tmpStr, 10, 64)
|
|
|
|
if errRet != nil {
|
|
|
|
err = fmt.Errorf("Parse conf error: heartbeat_timeout is incorrect")
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
cfg.HeartBeatTimeout = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2018-04-10 11:46:49 +02:00
|
|
|
|
|
|
|
func (cfg *ServerCommonConf) Check() (err error) {
|
|
|
|
return
|
|
|
|
}
|