proxy.go 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. // Copyright 2016 fatedier, fatedier@gmail.com
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package config
  15. import (
  16. "fmt"
  17. "reflect"
  18. "strconv"
  19. "strings"
  20. "github.com/fatedier/frp/models/consts"
  21. "github.com/fatedier/frp/models/msg"
  22. "github.com/fatedier/frp/utils/util"
  23. ini "github.com/vaughan0/go-ini"
  24. )
  25. var (
  26. proxyConfTypeMap map[string]reflect.Type
  27. )
  28. func init() {
  29. proxyConfTypeMap = make(map[string]reflect.Type)
  30. proxyConfTypeMap[consts.TcpProxy] = reflect.TypeOf(TcpProxyConf{})
  31. proxyConfTypeMap[consts.UdpProxy] = reflect.TypeOf(UdpProxyConf{})
  32. proxyConfTypeMap[consts.HttpProxy] = reflect.TypeOf(HttpProxyConf{})
  33. proxyConfTypeMap[consts.HttpsProxy] = reflect.TypeOf(HttpsProxyConf{})
  34. proxyConfTypeMap[consts.StcpProxy] = reflect.TypeOf(StcpProxyConf{})
  35. proxyConfTypeMap[consts.XtcpProxy] = reflect.TypeOf(XtcpProxyConf{})
  36. }
  37. // NewConfByType creates a empty ProxyConf object by proxyType.
  38. // If proxyType isn't exist, return nil.
  39. func NewConfByType(proxyType string) ProxyConf {
  40. v, ok := proxyConfTypeMap[proxyType]
  41. if !ok {
  42. return nil
  43. }
  44. cfg := reflect.New(v).Interface().(ProxyConf)
  45. return cfg
  46. }
  47. type ProxyConf interface {
  48. GetBaseInfo() *BaseProxyConf
  49. UnmarshalFromMsg(pMsg *msg.NewProxy)
  50. UnmarshalFromIni(prefix string, name string, conf ini.Section) error
  51. MarshalToMsg(pMsg *msg.NewProxy)
  52. CheckForCli() error
  53. CheckForSvr(serverCfg ServerCommonConf) error
  54. Compare(conf ProxyConf) bool
  55. }
  56. func NewProxyConfFromMsg(pMsg *msg.NewProxy, serverCfg ServerCommonConf) (cfg ProxyConf, err error) {
  57. if pMsg.ProxyType == "" {
  58. pMsg.ProxyType = consts.TcpProxy
  59. }
  60. cfg = NewConfByType(pMsg.ProxyType)
  61. if cfg == nil {
  62. err = fmt.Errorf("proxy [%s] type [%s] error", pMsg.ProxyName, pMsg.ProxyType)
  63. return
  64. }
  65. cfg.UnmarshalFromMsg(pMsg)
  66. err = cfg.CheckForSvr(serverCfg)
  67. return
  68. }
  69. func NewProxyConfFromIni(prefix string, name string, section ini.Section) (cfg ProxyConf, err error) {
  70. proxyType := section["type"]
  71. if proxyType == "" {
  72. proxyType = consts.TcpProxy
  73. section["type"] = consts.TcpProxy
  74. }
  75. cfg = NewConfByType(proxyType)
  76. if cfg == nil {
  77. err = fmt.Errorf("proxy [%s] type [%s] error", name, proxyType)
  78. return
  79. }
  80. if err = cfg.UnmarshalFromIni(prefix, name, section); err != nil {
  81. return
  82. }
  83. if err = cfg.CheckForCli(); err != nil {
  84. return
  85. }
  86. return
  87. }
  88. // BaseProxyConf provides configuration info that is common to all proxy types.
  89. type BaseProxyConf struct {
  90. // ProxyName is the name of this proxy.
  91. ProxyName string `json:"proxy_name"`
  92. // ProxyType specifies the type of this proxy. Valid values include "tcp",
  93. // "udp", "http", "https", "stcp", and "xtcp". By default, this value is
  94. // "tcp".
  95. ProxyType string `json:"proxy_type"`
  96. // UseEncryption controls whether or not communication with the server will
  97. // be encrypted. Encryption is done using the tokens supplied in the server
  98. // and client configuration. By default, this value is false.
  99. UseEncryption bool `json:"use_encryption"`
  100. // UseCompression controls whether or not communication with the server
  101. // will be compressed. By default, this value is false.
  102. UseCompression bool `json:"use_compression"`
  103. // Group specifies which group the proxy is a part of. The server will use
  104. // this information to load balance proxies in the same group. If the value
  105. // is "", this proxy will not be in a group. By default, this value is "".
  106. Group string `json:"group"`
  107. // GroupKey specifies a group key, which should be the same among proxies
  108. // of the same group. By default, this value is "".
  109. GroupKey string `json:"group_key"`
  110. // ProxyProtocolVersion specifies which protocol version to use. Valid
  111. // values include "v1", "v2", and "". If the value is "", a protocol
  112. // version will be automatically selected. By default, this value is "".
  113. ProxyProtocolVersion string `json:"proxy_protocol_version"`
  114. LocalSvrConf
  115. HealthCheckConf
  116. }
  117. func (cfg *BaseProxyConf) GetBaseInfo() *BaseProxyConf {
  118. return cfg
  119. }
  120. func (cfg *BaseProxyConf) compare(cmp *BaseProxyConf) bool {
  121. if cfg.ProxyName != cmp.ProxyName ||
  122. cfg.ProxyType != cmp.ProxyType ||
  123. cfg.UseEncryption != cmp.UseEncryption ||
  124. cfg.UseCompression != cmp.UseCompression ||
  125. cfg.Group != cmp.Group ||
  126. cfg.GroupKey != cmp.GroupKey ||
  127. cfg.ProxyProtocolVersion != cmp.ProxyProtocolVersion {
  128. return false
  129. }
  130. if !cfg.LocalSvrConf.compare(&cmp.LocalSvrConf) {
  131. return false
  132. }
  133. if !cfg.HealthCheckConf.compare(&cmp.HealthCheckConf) {
  134. return false
  135. }
  136. return true
  137. }
  138. func (cfg *BaseProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
  139. cfg.ProxyName = pMsg.ProxyName
  140. cfg.ProxyType = pMsg.ProxyType
  141. cfg.UseEncryption = pMsg.UseEncryption
  142. cfg.UseCompression = pMsg.UseCompression
  143. cfg.Group = pMsg.Group
  144. cfg.GroupKey = pMsg.GroupKey
  145. }
  146. func (cfg *BaseProxyConf) UnmarshalFromIni(prefix string, name string, section ini.Section) error {
  147. var (
  148. tmpStr string
  149. ok bool
  150. )
  151. cfg.ProxyName = prefix + name
  152. cfg.ProxyType = section["type"]
  153. tmpStr, ok = section["use_encryption"]
  154. if ok && tmpStr == "true" {
  155. cfg.UseEncryption = true
  156. }
  157. tmpStr, ok = section["use_compression"]
  158. if ok && tmpStr == "true" {
  159. cfg.UseCompression = true
  160. }
  161. cfg.Group = section["group"]
  162. cfg.GroupKey = section["group_key"]
  163. cfg.ProxyProtocolVersion = section["proxy_protocol_version"]
  164. if err := cfg.LocalSvrConf.UnmarshalFromIni(prefix, name, section); err != nil {
  165. return err
  166. }
  167. if err := cfg.HealthCheckConf.UnmarshalFromIni(prefix, name, section); err != nil {
  168. return err
  169. }
  170. if cfg.HealthCheckType == "tcp" && cfg.Plugin == "" {
  171. cfg.HealthCheckAddr = cfg.LocalIp + fmt.Sprintf(":%d", cfg.LocalPort)
  172. }
  173. if cfg.HealthCheckType == "http" && cfg.Plugin == "" && cfg.HealthCheckUrl != "" {
  174. s := fmt.Sprintf("http://%s:%d", cfg.LocalIp, cfg.LocalPort)
  175. if !strings.HasPrefix(cfg.HealthCheckUrl, "/") {
  176. s += "/"
  177. }
  178. cfg.HealthCheckUrl = s + cfg.HealthCheckUrl
  179. }
  180. return nil
  181. }
  182. func (cfg *BaseProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
  183. pMsg.ProxyName = cfg.ProxyName
  184. pMsg.ProxyType = cfg.ProxyType
  185. pMsg.UseEncryption = cfg.UseEncryption
  186. pMsg.UseCompression = cfg.UseCompression
  187. pMsg.Group = cfg.Group
  188. pMsg.GroupKey = cfg.GroupKey
  189. }
  190. func (cfg *BaseProxyConf) checkForCli() (err error) {
  191. if cfg.ProxyProtocolVersion != "" {
  192. if cfg.ProxyProtocolVersion != "v1" && cfg.ProxyProtocolVersion != "v2" {
  193. return fmt.Errorf("no support proxy protocol version: %s", cfg.ProxyProtocolVersion)
  194. }
  195. }
  196. if err = cfg.LocalSvrConf.checkForCli(); err != nil {
  197. return
  198. }
  199. if err = cfg.HealthCheckConf.checkForCli(); err != nil {
  200. return
  201. }
  202. return nil
  203. }
  204. // Bind info
  205. type BindInfoConf struct {
  206. RemotePort int `json:"remote_port"`
  207. }
  208. func (cfg *BindInfoConf) compare(cmp *BindInfoConf) bool {
  209. if cfg.RemotePort != cmp.RemotePort {
  210. return false
  211. }
  212. return true
  213. }
  214. func (cfg *BindInfoConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
  215. cfg.RemotePort = pMsg.RemotePort
  216. }
  217. func (cfg *BindInfoConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) {
  218. var (
  219. tmpStr string
  220. ok bool
  221. v int64
  222. )
  223. if tmpStr, ok = section["remote_port"]; ok {
  224. if v, err = strconv.ParseInt(tmpStr, 10, 64); err != nil {
  225. return fmt.Errorf("Parse conf error: proxy [%s] remote_port error", name)
  226. } else {
  227. cfg.RemotePort = int(v)
  228. }
  229. } else {
  230. return fmt.Errorf("Parse conf error: proxy [%s] remote_port not found", name)
  231. }
  232. return nil
  233. }
  234. func (cfg *BindInfoConf) MarshalToMsg(pMsg *msg.NewProxy) {
  235. pMsg.RemotePort = cfg.RemotePort
  236. }
  237. // Domain info
  238. type DomainConf struct {
  239. CustomDomains []string `json:"custom_domains"`
  240. SubDomain string `json:"sub_domain"`
  241. }
  242. func (cfg *DomainConf) compare(cmp *DomainConf) bool {
  243. if strings.Join(cfg.CustomDomains, " ") != strings.Join(cmp.CustomDomains, " ") ||
  244. cfg.SubDomain != cmp.SubDomain {
  245. return false
  246. }
  247. return true
  248. }
  249. func (cfg *DomainConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
  250. cfg.CustomDomains = pMsg.CustomDomains
  251. cfg.SubDomain = pMsg.SubDomain
  252. }
  253. func (cfg *DomainConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) {
  254. var (
  255. tmpStr string
  256. ok bool
  257. )
  258. if tmpStr, ok = section["custom_domains"]; ok {
  259. cfg.CustomDomains = strings.Split(tmpStr, ",")
  260. for i, domain := range cfg.CustomDomains {
  261. cfg.CustomDomains[i] = strings.ToLower(strings.TrimSpace(domain))
  262. }
  263. }
  264. if tmpStr, ok = section["subdomain"]; ok {
  265. cfg.SubDomain = tmpStr
  266. }
  267. return
  268. }
  269. func (cfg *DomainConf) MarshalToMsg(pMsg *msg.NewProxy) {
  270. pMsg.CustomDomains = cfg.CustomDomains
  271. pMsg.SubDomain = cfg.SubDomain
  272. }
  273. func (cfg *DomainConf) check() (err error) {
  274. if len(cfg.CustomDomains) == 0 && cfg.SubDomain == "" {
  275. err = fmt.Errorf("custom_domains and subdomain should set at least one of them")
  276. return
  277. }
  278. return
  279. }
  280. func (cfg *DomainConf) checkForCli() (err error) {
  281. if err = cfg.check(); err != nil {
  282. return
  283. }
  284. return
  285. }
  286. func (cfg *DomainConf) checkForSvr(serverCfg ServerCommonConf) (err error) {
  287. if err = cfg.check(); err != nil {
  288. return
  289. }
  290. for _, domain := range cfg.CustomDomains {
  291. if serverCfg.SubDomainHost != "" && len(strings.Split(serverCfg.SubDomainHost, ".")) < len(strings.Split(domain, ".")) {
  292. if strings.Contains(domain, serverCfg.SubDomainHost) {
  293. return fmt.Errorf("custom domain [%s] should not belong to subdomain_host [%s]", domain, serverCfg.SubDomainHost)
  294. }
  295. }
  296. }
  297. if cfg.SubDomain != "" {
  298. if serverCfg.SubDomainHost == "" {
  299. return fmt.Errorf("subdomain is not supported because this feature is not enabled in remote frps")
  300. }
  301. if strings.Contains(cfg.SubDomain, ".") || strings.Contains(cfg.SubDomain, "*") {
  302. return fmt.Errorf("'.' and '*' is not supported in subdomain")
  303. }
  304. }
  305. return
  306. }
  307. // LocalSvrConf configures what location the client will proxy to, or what
  308. // plugin will be used.
  309. type LocalSvrConf struct {
  310. // LocalIp specifies the IP address or host name to proxy to.
  311. LocalIp string `json:"local_ip"`
  312. // LocalPort specifies the port to proxy to.
  313. LocalPort int `json:"local_port"`
  314. // Plugin specifies what plugin should be used for proxying. If this value
  315. // is set, the LocalIp and LocalPort values will be ignored. By default,
  316. // this value is "".
  317. Plugin string `json:"plugin"`
  318. // PluginParams specify parameters to be passed to the plugin, if one is
  319. // being used. By default, this value is an empty map.
  320. PluginParams map[string]string `json:"plugin_params"`
  321. }
  322. func (cfg *LocalSvrConf) compare(cmp *LocalSvrConf) bool {
  323. if cfg.LocalIp != cmp.LocalIp ||
  324. cfg.LocalPort != cmp.LocalPort {
  325. return false
  326. }
  327. if cfg.Plugin != cmp.Plugin ||
  328. len(cfg.PluginParams) != len(cmp.PluginParams) {
  329. return false
  330. }
  331. for k, v := range cfg.PluginParams {
  332. value, ok := cmp.PluginParams[k]
  333. if !ok || v != value {
  334. return false
  335. }
  336. }
  337. return true
  338. }
  339. func (cfg *LocalSvrConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) {
  340. cfg.Plugin = section["plugin"]
  341. cfg.PluginParams = make(map[string]string)
  342. if cfg.Plugin != "" {
  343. // get params begin with "plugin_"
  344. for k, v := range section {
  345. if strings.HasPrefix(k, "plugin_") {
  346. cfg.PluginParams[k] = v
  347. }
  348. }
  349. } else {
  350. if cfg.LocalIp = section["local_ip"]; cfg.LocalIp == "" {
  351. cfg.LocalIp = "127.0.0.1"
  352. }
  353. if tmpStr, ok := section["local_port"]; ok {
  354. if cfg.LocalPort, err = strconv.Atoi(tmpStr); err != nil {
  355. return fmt.Errorf("Parse conf error: proxy [%s] local_port error", name)
  356. }
  357. } else {
  358. return fmt.Errorf("Parse conf error: proxy [%s] local_port not found", name)
  359. }
  360. }
  361. return
  362. }
  363. func (cfg *LocalSvrConf) checkForCli() (err error) {
  364. if cfg.Plugin == "" {
  365. if cfg.LocalIp == "" {
  366. err = fmt.Errorf("local ip or plugin is required")
  367. return
  368. }
  369. if cfg.LocalPort <= 0 {
  370. err = fmt.Errorf("error local_port")
  371. return
  372. }
  373. }
  374. return
  375. }
  376. // HealthCheckConf configures health checking. This can be useful for load
  377. // balancing purposes to detect and remove proxies to failing services.
  378. type HealthCheckConf struct {
  379. // HealthCheckType specifies what protocol to use for health checking.
  380. // Valid values include "tcp", "http", and "". If this value is "", health
  381. // checking will not be performed. By default, this value is "".
  382. //
  383. // If the type is "tcp", a connection will be attempted to the target
  384. // server. If a connection cannot be established, the health check fails.
  385. //
  386. // If the type is "http", a GET request will be made to the endpoint
  387. // specified by HealthCheckUrl. If the response is not a 200, the health
  388. // check fails.
  389. HealthCheckType string `json:"health_check_type"` // tcp | http
  390. // HealthCheckTimeoutS specifies the number of seconds to wait for a health
  391. // check attempt to connect. If the timeout is reached, this counts as a
  392. // health check failure. By default, this value is 3.
  393. HealthCheckTimeoutS int `json:"health_check_timeout_s"`
  394. // HealthCheckMaxFailed specifies the number of allowed failures before the
  395. // proxy is stopped. By default, this value is 1.
  396. HealthCheckMaxFailed int `json:"health_check_max_failed"`
  397. // HealthCheckIntervalS specifies the time in seconds between health
  398. // checks. By default, this value is 10.
  399. HealthCheckIntervalS int `json:"health_check_interval_s"`
  400. // HealthCheckUrl specifies the address to send health checks to if the
  401. // health check type is "http".
  402. HealthCheckUrl string `json:"health_check_url"`
  403. // HealthCheckAddr specifies the address to connect to if the health check
  404. // type is "tcp".
  405. HealthCheckAddr string `json:"-"`
  406. }
  407. func (cfg *HealthCheckConf) compare(cmp *HealthCheckConf) bool {
  408. if cfg.HealthCheckType != cmp.HealthCheckType ||
  409. cfg.HealthCheckTimeoutS != cmp.HealthCheckTimeoutS ||
  410. cfg.HealthCheckMaxFailed != cmp.HealthCheckMaxFailed ||
  411. cfg.HealthCheckIntervalS != cmp.HealthCheckIntervalS ||
  412. cfg.HealthCheckUrl != cmp.HealthCheckUrl {
  413. return false
  414. }
  415. return true
  416. }
  417. func (cfg *HealthCheckConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) {
  418. cfg.HealthCheckType = section["health_check_type"]
  419. cfg.HealthCheckUrl = section["health_check_url"]
  420. if tmpStr, ok := section["health_check_timeout_s"]; ok {
  421. if cfg.HealthCheckTimeoutS, err = strconv.Atoi(tmpStr); err != nil {
  422. return fmt.Errorf("Parse conf error: proxy [%s] health_check_timeout_s error", name)
  423. }
  424. }
  425. if tmpStr, ok := section["health_check_max_failed"]; ok {
  426. if cfg.HealthCheckMaxFailed, err = strconv.Atoi(tmpStr); err != nil {
  427. return fmt.Errorf("Parse conf error: proxy [%s] health_check_max_failed error", name)
  428. }
  429. }
  430. if tmpStr, ok := section["health_check_interval_s"]; ok {
  431. if cfg.HealthCheckIntervalS, err = strconv.Atoi(tmpStr); err != nil {
  432. return fmt.Errorf("Parse conf error: proxy [%s] health_check_interval_s error", name)
  433. }
  434. }
  435. return
  436. }
  437. func (cfg *HealthCheckConf) checkForCli() error {
  438. if cfg.HealthCheckType != "" && cfg.HealthCheckType != "tcp" && cfg.HealthCheckType != "http" {
  439. return fmt.Errorf("unsupport health check type")
  440. }
  441. if cfg.HealthCheckType != "" {
  442. if cfg.HealthCheckType == "http" && cfg.HealthCheckUrl == "" {
  443. return fmt.Errorf("health_check_url is required for health check type 'http'")
  444. }
  445. }
  446. return nil
  447. }
  448. // TCP
  449. type TcpProxyConf struct {
  450. BaseProxyConf
  451. BindInfoConf
  452. }
  453. func (cfg *TcpProxyConf) Compare(cmp ProxyConf) bool {
  454. cmpConf, ok := cmp.(*TcpProxyConf)
  455. if !ok {
  456. return false
  457. }
  458. if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) ||
  459. !cfg.BindInfoConf.compare(&cmpConf.BindInfoConf) {
  460. return false
  461. }
  462. return true
  463. }
  464. func (cfg *TcpProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
  465. cfg.BaseProxyConf.UnmarshalFromMsg(pMsg)
  466. cfg.BindInfoConf.UnmarshalFromMsg(pMsg)
  467. }
  468. func (cfg *TcpProxyConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) {
  469. if err = cfg.BaseProxyConf.UnmarshalFromIni(prefix, name, section); err != nil {
  470. return
  471. }
  472. if err = cfg.BindInfoConf.UnmarshalFromIni(prefix, name, section); err != nil {
  473. return
  474. }
  475. return
  476. }
  477. func (cfg *TcpProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
  478. cfg.BaseProxyConf.MarshalToMsg(pMsg)
  479. cfg.BindInfoConf.MarshalToMsg(pMsg)
  480. }
  481. func (cfg *TcpProxyConf) CheckForCli() (err error) {
  482. if err = cfg.BaseProxyConf.checkForCli(); err != nil {
  483. return err
  484. }
  485. return
  486. }
  487. func (cfg *TcpProxyConf) CheckForSvr(serverCfg ServerCommonConf) error { return nil }
  488. // UDP
  489. type UdpProxyConf struct {
  490. BaseProxyConf
  491. BindInfoConf
  492. }
  493. func (cfg *UdpProxyConf) Compare(cmp ProxyConf) bool {
  494. cmpConf, ok := cmp.(*UdpProxyConf)
  495. if !ok {
  496. return false
  497. }
  498. if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) ||
  499. !cfg.BindInfoConf.compare(&cmpConf.BindInfoConf) {
  500. return false
  501. }
  502. return true
  503. }
  504. func (cfg *UdpProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
  505. cfg.BaseProxyConf.UnmarshalFromMsg(pMsg)
  506. cfg.BindInfoConf.UnmarshalFromMsg(pMsg)
  507. }
  508. func (cfg *UdpProxyConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) {
  509. if err = cfg.BaseProxyConf.UnmarshalFromIni(prefix, name, section); err != nil {
  510. return
  511. }
  512. if err = cfg.BindInfoConf.UnmarshalFromIni(prefix, name, section); err != nil {
  513. return
  514. }
  515. return
  516. }
  517. func (cfg *UdpProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
  518. cfg.BaseProxyConf.MarshalToMsg(pMsg)
  519. cfg.BindInfoConf.MarshalToMsg(pMsg)
  520. }
  521. func (cfg *UdpProxyConf) CheckForCli() (err error) {
  522. if err = cfg.BaseProxyConf.checkForCli(); err != nil {
  523. return
  524. }
  525. return
  526. }
  527. func (cfg *UdpProxyConf) CheckForSvr(serverCfg ServerCommonConf) error { return nil }
  528. // HTTP
  529. type HttpProxyConf struct {
  530. BaseProxyConf
  531. DomainConf
  532. Locations []string `json:"locations"`
  533. HttpUser string `json:"http_user"`
  534. HttpPwd string `json:"http_pwd"`
  535. HostHeaderRewrite string `json:"host_header_rewrite"`
  536. Headers map[string]string `json:"headers"`
  537. }
  538. func (cfg *HttpProxyConf) Compare(cmp ProxyConf) bool {
  539. cmpConf, ok := cmp.(*HttpProxyConf)
  540. if !ok {
  541. return false
  542. }
  543. if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) ||
  544. !cfg.DomainConf.compare(&cmpConf.DomainConf) ||
  545. strings.Join(cfg.Locations, " ") != strings.Join(cmpConf.Locations, " ") ||
  546. cfg.HostHeaderRewrite != cmpConf.HostHeaderRewrite ||
  547. cfg.HttpUser != cmpConf.HttpUser ||
  548. cfg.HttpPwd != cmpConf.HttpPwd ||
  549. len(cfg.Headers) != len(cmpConf.Headers) {
  550. return false
  551. }
  552. for k, v := range cfg.Headers {
  553. if v2, ok := cmpConf.Headers[k]; !ok {
  554. return false
  555. } else {
  556. if v != v2 {
  557. return false
  558. }
  559. }
  560. }
  561. return true
  562. }
  563. func (cfg *HttpProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
  564. cfg.BaseProxyConf.UnmarshalFromMsg(pMsg)
  565. cfg.DomainConf.UnmarshalFromMsg(pMsg)
  566. cfg.Locations = pMsg.Locations
  567. cfg.HostHeaderRewrite = pMsg.HostHeaderRewrite
  568. cfg.HttpUser = pMsg.HttpUser
  569. cfg.HttpPwd = pMsg.HttpPwd
  570. cfg.Headers = pMsg.Headers
  571. }
  572. func (cfg *HttpProxyConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) {
  573. if err = cfg.BaseProxyConf.UnmarshalFromIni(prefix, name, section); err != nil {
  574. return
  575. }
  576. if err = cfg.DomainConf.UnmarshalFromIni(prefix, name, section); err != nil {
  577. return
  578. }
  579. var (
  580. tmpStr string
  581. ok bool
  582. )
  583. if tmpStr, ok = section["locations"]; ok {
  584. cfg.Locations = strings.Split(tmpStr, ",")
  585. } else {
  586. cfg.Locations = []string{""}
  587. }
  588. cfg.HostHeaderRewrite = section["host_header_rewrite"]
  589. cfg.HttpUser = section["http_user"]
  590. cfg.HttpPwd = section["http_pwd"]
  591. cfg.Headers = make(map[string]string)
  592. for k, v := range section {
  593. if strings.HasPrefix(k, "header_") {
  594. cfg.Headers[strings.TrimPrefix(k, "header_")] = v
  595. }
  596. }
  597. return
  598. }
  599. func (cfg *HttpProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
  600. cfg.BaseProxyConf.MarshalToMsg(pMsg)
  601. cfg.DomainConf.MarshalToMsg(pMsg)
  602. pMsg.Locations = cfg.Locations
  603. pMsg.HostHeaderRewrite = cfg.HostHeaderRewrite
  604. pMsg.HttpUser = cfg.HttpUser
  605. pMsg.HttpPwd = cfg.HttpPwd
  606. pMsg.Headers = cfg.Headers
  607. }
  608. func (cfg *HttpProxyConf) CheckForCli() (err error) {
  609. if err = cfg.BaseProxyConf.checkForCli(); err != nil {
  610. return
  611. }
  612. if err = cfg.DomainConf.checkForCli(); err != nil {
  613. return
  614. }
  615. return
  616. }
  617. func (cfg *HttpProxyConf) CheckForSvr(serverCfg ServerCommonConf) (err error) {
  618. if serverCfg.VhostHttpPort == 0 {
  619. return fmt.Errorf("type [http] not support when vhost_http_port is not set")
  620. }
  621. if err = cfg.DomainConf.checkForSvr(serverCfg); err != nil {
  622. err = fmt.Errorf("proxy [%s] domain conf check error: %v", cfg.ProxyName, err)
  623. return
  624. }
  625. return
  626. }
  627. // HTTPS
  628. type HttpsProxyConf struct {
  629. BaseProxyConf
  630. DomainConf
  631. }
  632. func (cfg *HttpsProxyConf) Compare(cmp ProxyConf) bool {
  633. cmpConf, ok := cmp.(*HttpsProxyConf)
  634. if !ok {
  635. return false
  636. }
  637. if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) ||
  638. !cfg.DomainConf.compare(&cmpConf.DomainConf) {
  639. return false
  640. }
  641. return true
  642. }
  643. func (cfg *HttpsProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
  644. cfg.BaseProxyConf.UnmarshalFromMsg(pMsg)
  645. cfg.DomainConf.UnmarshalFromMsg(pMsg)
  646. }
  647. func (cfg *HttpsProxyConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) {
  648. if err = cfg.BaseProxyConf.UnmarshalFromIni(prefix, name, section); err != nil {
  649. return
  650. }
  651. if err = cfg.DomainConf.UnmarshalFromIni(prefix, name, section); err != nil {
  652. return
  653. }
  654. return
  655. }
  656. func (cfg *HttpsProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
  657. cfg.BaseProxyConf.MarshalToMsg(pMsg)
  658. cfg.DomainConf.MarshalToMsg(pMsg)
  659. }
  660. func (cfg *HttpsProxyConf) CheckForCli() (err error) {
  661. if err = cfg.BaseProxyConf.checkForCli(); err != nil {
  662. return
  663. }
  664. if err = cfg.DomainConf.checkForCli(); err != nil {
  665. return
  666. }
  667. return
  668. }
  669. func (cfg *HttpsProxyConf) CheckForSvr(serverCfg ServerCommonConf) (err error) {
  670. if serverCfg.VhostHttpsPort == 0 {
  671. return fmt.Errorf("type [https] not support when vhost_https_port is not set")
  672. }
  673. if err = cfg.DomainConf.checkForSvr(serverCfg); err != nil {
  674. err = fmt.Errorf("proxy [%s] domain conf check error: %v", cfg.ProxyName, err)
  675. return
  676. }
  677. return
  678. }
  679. // STCP
  680. type StcpProxyConf struct {
  681. BaseProxyConf
  682. Role string `json:"role"`
  683. Sk string `json:"sk"`
  684. }
  685. func (cfg *StcpProxyConf) Compare(cmp ProxyConf) bool {
  686. cmpConf, ok := cmp.(*StcpProxyConf)
  687. if !ok {
  688. return false
  689. }
  690. if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) ||
  691. cfg.Role != cmpConf.Role ||
  692. cfg.Sk != cmpConf.Sk {
  693. return false
  694. }
  695. return true
  696. }
  697. // Only for role server.
  698. func (cfg *StcpProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
  699. cfg.BaseProxyConf.UnmarshalFromMsg(pMsg)
  700. cfg.Sk = pMsg.Sk
  701. }
  702. func (cfg *StcpProxyConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) {
  703. if err = cfg.BaseProxyConf.UnmarshalFromIni(prefix, name, section); err != nil {
  704. return
  705. }
  706. cfg.Role = section["role"]
  707. if cfg.Role != "server" {
  708. return fmt.Errorf("Parse conf error: proxy [%s] incorrect role [%s]", name, cfg.Role)
  709. }
  710. cfg.Sk = section["sk"]
  711. if err = cfg.LocalSvrConf.UnmarshalFromIni(prefix, name, section); err != nil {
  712. return
  713. }
  714. return
  715. }
  716. func (cfg *StcpProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
  717. cfg.BaseProxyConf.MarshalToMsg(pMsg)
  718. pMsg.Sk = cfg.Sk
  719. }
  720. func (cfg *StcpProxyConf) CheckForCli() (err error) {
  721. if err = cfg.BaseProxyConf.checkForCli(); err != nil {
  722. return
  723. }
  724. if cfg.Role != "server" {
  725. err = fmt.Errorf("role should be 'server'")
  726. return
  727. }
  728. return
  729. }
  730. func (cfg *StcpProxyConf) CheckForSvr(serverCfg ServerCommonConf) (err error) {
  731. return
  732. }
  733. // XTCP
  734. type XtcpProxyConf struct {
  735. BaseProxyConf
  736. Role string `json:"role"`
  737. Sk string `json:"sk"`
  738. }
  739. func (cfg *XtcpProxyConf) Compare(cmp ProxyConf) bool {
  740. cmpConf, ok := cmp.(*XtcpProxyConf)
  741. if !ok {
  742. return false
  743. }
  744. if !cfg.BaseProxyConf.compare(&cmpConf.BaseProxyConf) ||
  745. !cfg.LocalSvrConf.compare(&cmpConf.LocalSvrConf) ||
  746. cfg.Role != cmpConf.Role ||
  747. cfg.Sk != cmpConf.Sk {
  748. return false
  749. }
  750. return true
  751. }
  752. // Only for role server.
  753. func (cfg *XtcpProxyConf) UnmarshalFromMsg(pMsg *msg.NewProxy) {
  754. cfg.BaseProxyConf.UnmarshalFromMsg(pMsg)
  755. cfg.Sk = pMsg.Sk
  756. }
  757. func (cfg *XtcpProxyConf) UnmarshalFromIni(prefix string, name string, section ini.Section) (err error) {
  758. if err = cfg.BaseProxyConf.UnmarshalFromIni(prefix, name, section); err != nil {
  759. return
  760. }
  761. cfg.Role = section["role"]
  762. if cfg.Role != "server" {
  763. return fmt.Errorf("Parse conf error: proxy [%s] incorrect role [%s]", name, cfg.Role)
  764. }
  765. cfg.Sk = section["sk"]
  766. if err = cfg.LocalSvrConf.UnmarshalFromIni(prefix, name, section); err != nil {
  767. return
  768. }
  769. return
  770. }
  771. func (cfg *XtcpProxyConf) MarshalToMsg(pMsg *msg.NewProxy) {
  772. cfg.BaseProxyConf.MarshalToMsg(pMsg)
  773. pMsg.Sk = cfg.Sk
  774. }
  775. func (cfg *XtcpProxyConf) CheckForCli() (err error) {
  776. if err = cfg.BaseProxyConf.checkForCli(); err != nil {
  777. return
  778. }
  779. if cfg.Role != "server" {
  780. err = fmt.Errorf("role should be 'server'")
  781. return
  782. }
  783. return
  784. }
  785. func (cfg *XtcpProxyConf) CheckForSvr(serverCfg ServerCommonConf) (err error) {
  786. return
  787. }
  788. func ParseRangeSection(name string, section ini.Section) (sections map[string]ini.Section, err error) {
  789. localPorts, errRet := util.ParseRangeNumbers(section["local_port"])
  790. if errRet != nil {
  791. err = fmt.Errorf("Parse conf error: range section [%s] local_port invalid, %v", name, errRet)
  792. return
  793. }
  794. remotePorts, errRet := util.ParseRangeNumbers(section["remote_port"])
  795. if errRet != nil {
  796. err = fmt.Errorf("Parse conf error: range section [%s] remote_port invalid, %v", name, errRet)
  797. return
  798. }
  799. if len(localPorts) != len(remotePorts) {
  800. err = fmt.Errorf("Parse conf error: range section [%s] local ports number should be same with remote ports number", name)
  801. return
  802. }
  803. if len(localPorts) == 0 {
  804. err = fmt.Errorf("Parse conf error: range section [%s] local_port and remote_port is necessary", name)
  805. return
  806. }
  807. sections = make(map[string]ini.Section)
  808. for i, port := range localPorts {
  809. subName := fmt.Sprintf("%s_%d", name, i)
  810. subSection := copySection(section)
  811. subSection["local_port"] = fmt.Sprintf("%d", port)
  812. subSection["remote_port"] = fmt.Sprintf("%d", remotePorts[i])
  813. sections[subName] = subSection
  814. }
  815. return
  816. }
  817. // if len(startProxy) is 0, start all
  818. // otherwise just start proxies in startProxy map
  819. func LoadAllConfFromIni(prefix string, content string, startProxy map[string]struct{}) (
  820. proxyConfs map[string]ProxyConf, visitorConfs map[string]VisitorConf, err error) {
  821. conf, errRet := ini.Load(strings.NewReader(content))
  822. if errRet != nil {
  823. err = errRet
  824. return
  825. }
  826. if prefix != "" {
  827. prefix += "."
  828. }
  829. startAll := true
  830. if len(startProxy) > 0 {
  831. startAll = false
  832. }
  833. proxyConfs = make(map[string]ProxyConf)
  834. visitorConfs = make(map[string]VisitorConf)
  835. for name, section := range conf {
  836. if name == "common" {
  837. continue
  838. }
  839. _, shouldStart := startProxy[name]
  840. if !startAll && !shouldStart {
  841. continue
  842. }
  843. subSections := make(map[string]ini.Section)
  844. if strings.HasPrefix(name, "range:") {
  845. // range section
  846. rangePrefix := strings.TrimSpace(strings.TrimPrefix(name, "range:"))
  847. subSections, err = ParseRangeSection(rangePrefix, section)
  848. if err != nil {
  849. return
  850. }
  851. } else {
  852. subSections[name] = section
  853. }
  854. for subName, subSection := range subSections {
  855. if subSection["role"] == "" {
  856. subSection["role"] = "server"
  857. }
  858. role := subSection["role"]
  859. if role == "server" {
  860. cfg, errRet := NewProxyConfFromIni(prefix, subName, subSection)
  861. if errRet != nil {
  862. err = errRet
  863. return
  864. }
  865. proxyConfs[prefix+subName] = cfg
  866. } else if role == "visitor" {
  867. cfg, errRet := NewVisitorConfFromIni(prefix, subName, subSection)
  868. if errRet != nil {
  869. err = errRet
  870. return
  871. }
  872. visitorConfs[prefix+subName] = cfg
  873. } else {
  874. err = fmt.Errorf("role should be 'server' or 'visitor'")
  875. return
  876. }
  877. }
  878. }
  879. return
  880. }
  881. func copySection(section ini.Section) (out ini.Section) {
  882. out = make(ini.Section)
  883. for k, v := range section {
  884. out[k] = v
  885. }
  886. return
  887. }