1
0

reverseproxy.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. package main
  2. import (
  3. "encoding/json"
  4. "log"
  5. "net/http"
  6. "path/filepath"
  7. "sort"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "imuslab.com/zoraxy/mod/auth"
  12. "imuslab.com/zoraxy/mod/dynamicproxy"
  13. "imuslab.com/zoraxy/mod/uptime"
  14. "imuslab.com/zoraxy/mod/utils"
  15. )
  16. var (
  17. dynamicProxyRouter *dynamicproxy.Router
  18. )
  19. // Add user customizable reverse proxy
  20. func ReverseProxtInit() {
  21. inboundPort := 80
  22. if sysdb.KeyExists("settings", "inbound") {
  23. sysdb.Read("settings", "inbound", &inboundPort)
  24. log.Println("Serving inbound port ", inboundPort)
  25. } else {
  26. log.Println("Inbound port not set. Using default (80)")
  27. }
  28. useTls := false
  29. sysdb.Read("settings", "usetls", &useTls)
  30. if useTls {
  31. log.Println("TLS mode enabled. Serving proxxy request with TLS")
  32. } else {
  33. log.Println("TLS mode disabled. Serving proxy request with plain http")
  34. }
  35. forceLatestTLSVersion := false
  36. sysdb.Read("settings", "forceLatestTLS", &forceLatestTLSVersion)
  37. if forceLatestTLSVersion {
  38. log.Println("Force latest TLS mode enabled. Minimum TLS LS version is set to v1.2")
  39. } else {
  40. log.Println("Force latest TLS mode disabled. Minimum TLS version is set to v1.0")
  41. }
  42. forceHttpsRedirect := false
  43. sysdb.Read("settings", "redirect", &forceHttpsRedirect)
  44. if forceHttpsRedirect {
  45. log.Println("Force HTTPS mode enabled")
  46. } else {
  47. log.Println("Force HTTPS mode disabled")
  48. }
  49. dprouter, err := dynamicproxy.NewDynamicProxy(dynamicproxy.RouterOption{
  50. HostUUID: nodeUUID,
  51. Port: inboundPort,
  52. UseTls: useTls,
  53. ForceTLSLatest: forceLatestTLSVersion,
  54. ForceHttpsRedirect: forceHttpsRedirect,
  55. TlsManager: tlsCertManager,
  56. RedirectRuleTable: redirectTable,
  57. GeodbStore: geodbStore,
  58. StatisticCollector: statisticCollector,
  59. })
  60. if err != nil {
  61. log.Println(err.Error())
  62. return
  63. }
  64. dynamicProxyRouter = dprouter
  65. //Load all conf from files
  66. confs, _ := filepath.Glob("./conf/proxy/*.config")
  67. for _, conf := range confs {
  68. record, err := LoadReverseProxyConfig(conf)
  69. if err != nil {
  70. log.Println("Failed to load "+filepath.Base(conf), err.Error())
  71. return
  72. }
  73. if record.ProxyType == "root" {
  74. dynamicProxyRouter.SetRootProxy(&dynamicproxy.RootOptions{
  75. ProxyLocation: record.ProxyTarget,
  76. RequireTLS: record.UseTLS,
  77. })
  78. } else if record.ProxyType == "subd" {
  79. dynamicProxyRouter.AddSubdomainRoutingService(&dynamicproxy.SubdOptions{
  80. MatchingDomain: record.Rootname,
  81. Domain: record.ProxyTarget,
  82. RequireTLS: record.UseTLS,
  83. SkipCertValidations: record.SkipTlsValidation,
  84. RequireBasicAuth: record.RequireBasicAuth,
  85. BasicAuthCredentials: record.BasicAuthCredentials,
  86. BasicAuthExceptionRules: record.BasicAuthExceptionRules,
  87. })
  88. } else if record.ProxyType == "vdir" {
  89. dynamicProxyRouter.AddVirtualDirectoryProxyService(&dynamicproxy.VdirOptions{
  90. RootName: record.Rootname,
  91. Domain: record.ProxyTarget,
  92. RequireTLS: record.UseTLS,
  93. SkipCertValidations: record.SkipTlsValidation,
  94. RequireBasicAuth: record.RequireBasicAuth,
  95. BasicAuthCredentials: record.BasicAuthCredentials,
  96. BasicAuthExceptionRules: record.BasicAuthExceptionRules,
  97. })
  98. } else {
  99. log.Println("Unsupported endpoint type: " + record.ProxyType + ". Skipping " + filepath.Base(conf))
  100. }
  101. }
  102. //Start Service
  103. //Not sure why but delay must be added if you have another
  104. //reverse proxy server in front of this service
  105. time.Sleep(300 * time.Millisecond)
  106. dynamicProxyRouter.StartProxyService()
  107. log.Println("Dynamic Reverse Proxy service started")
  108. //Add all proxy services to uptime monitor
  109. //Create a uptime monitor service
  110. go func() {
  111. //This must be done in go routine to prevent blocking on system startup
  112. uptimeMonitor, _ = uptime.NewUptimeMonitor(&uptime.Config{
  113. Targets: GetUptimeTargetsFromReverseProxyRules(dynamicProxyRouter),
  114. Interval: 300, //5 minutes
  115. MaxRecordsStore: 288, //1 day
  116. })
  117. log.Println("Uptime Monitor background service started")
  118. }()
  119. }
  120. func ReverseProxyHandleOnOff(w http.ResponseWriter, r *http.Request) {
  121. enable, _ := utils.PostPara(r, "enable") //Support root, vdir and subd
  122. if enable == "true" {
  123. err := dynamicProxyRouter.StartProxyService()
  124. if err != nil {
  125. utils.SendErrorResponse(w, err.Error())
  126. return
  127. }
  128. } else {
  129. //Check if it is loopback
  130. if dynamicProxyRouter.IsProxiedSubdomain(r) {
  131. //Loopback routing. Turning it off will make the user lost control
  132. //of the whole system. Do not allow shutdown
  133. utils.SendErrorResponse(w, "Unable to shutdown in loopback rp mode. Remove proxy rules for management interface and retry.")
  134. return
  135. }
  136. err := dynamicProxyRouter.StopProxyService()
  137. if err != nil {
  138. utils.SendErrorResponse(w, err.Error())
  139. return
  140. }
  141. }
  142. utils.SendOK(w)
  143. }
  144. func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
  145. eptype, err := utils.PostPara(r, "type") //Support root, vdir and subd
  146. if err != nil {
  147. utils.SendErrorResponse(w, "type not defined")
  148. return
  149. }
  150. endpoint, err := utils.PostPara(r, "ep")
  151. if err != nil {
  152. utils.SendErrorResponse(w, "endpoint not defined")
  153. return
  154. }
  155. tls, _ := utils.PostPara(r, "tls")
  156. if tls == "" {
  157. tls = "false"
  158. }
  159. useTLS := (tls == "true")
  160. stv, _ := utils.PostPara(r, "tlsval")
  161. if stv == "" {
  162. stv = "false"
  163. }
  164. skipTlsValidation := (stv == "true")
  165. rba, _ := utils.PostPara(r, "bauth")
  166. if rba == "" {
  167. rba = "false"
  168. }
  169. requireBasicAuth := (rba == "true")
  170. //Prase the basic auth to correct structure
  171. cred, _ := utils.PostPara(r, "cred")
  172. basicAuthCredentials := []*dynamicproxy.BasicAuthCredentials{}
  173. if requireBasicAuth {
  174. preProcessCredentials := []*dynamicproxy.BasicAuthUnhashedCredentials{}
  175. err = json.Unmarshal([]byte(cred), &preProcessCredentials)
  176. if err != nil {
  177. utils.SendErrorResponse(w, "invalid user credentials")
  178. return
  179. }
  180. //Check if there are empty password credentials
  181. for _, credObj := range preProcessCredentials {
  182. if strings.TrimSpace(credObj.Password) == "" {
  183. utils.SendErrorResponse(w, credObj.Username+" has empty password")
  184. return
  185. }
  186. }
  187. //Convert and hash the passwords
  188. for _, credObj := range preProcessCredentials {
  189. basicAuthCredentials = append(basicAuthCredentials, &dynamicproxy.BasicAuthCredentials{
  190. Username: credObj.Username,
  191. PasswordHash: auth.Hash(credObj.Password),
  192. })
  193. }
  194. }
  195. rootname := ""
  196. if eptype == "vdir" {
  197. vdir, err := utils.PostPara(r, "rootname")
  198. if err != nil {
  199. utils.SendErrorResponse(w, "vdir not defined")
  200. return
  201. }
  202. //Vdir must start with /
  203. if !strings.HasPrefix(vdir, "/") {
  204. vdir = "/" + vdir
  205. }
  206. rootname = vdir
  207. thisOption := dynamicproxy.VdirOptions{
  208. RootName: vdir,
  209. Domain: endpoint,
  210. RequireTLS: useTLS,
  211. SkipCertValidations: skipTlsValidation,
  212. RequireBasicAuth: requireBasicAuth,
  213. BasicAuthCredentials: basicAuthCredentials,
  214. }
  215. dynamicProxyRouter.AddVirtualDirectoryProxyService(&thisOption)
  216. } else if eptype == "subd" {
  217. subdomain, err := utils.PostPara(r, "rootname")
  218. if err != nil {
  219. utils.SendErrorResponse(w, "subdomain not defined")
  220. return
  221. }
  222. rootname = subdomain
  223. thisOption := dynamicproxy.SubdOptions{
  224. MatchingDomain: subdomain,
  225. Domain: endpoint,
  226. RequireTLS: useTLS,
  227. SkipCertValidations: skipTlsValidation,
  228. RequireBasicAuth: requireBasicAuth,
  229. BasicAuthCredentials: basicAuthCredentials,
  230. }
  231. dynamicProxyRouter.AddSubdomainRoutingService(&thisOption)
  232. } else if eptype == "root" {
  233. rootname = "root"
  234. thisOption := dynamicproxy.RootOptions{
  235. ProxyLocation: endpoint,
  236. RequireTLS: useTLS,
  237. }
  238. dynamicProxyRouter.SetRootProxy(&thisOption)
  239. } else {
  240. //Invalid eptype
  241. utils.SendErrorResponse(w, "Invalid endpoint type")
  242. return
  243. }
  244. //Save it
  245. thisProxyConfigRecord := Record{
  246. ProxyType: eptype,
  247. Rootname: rootname,
  248. ProxyTarget: endpoint,
  249. UseTLS: useTLS,
  250. SkipTlsValidation: skipTlsValidation,
  251. RequireBasicAuth: requireBasicAuth,
  252. BasicAuthCredentials: basicAuthCredentials,
  253. }
  254. SaveReverseProxyConfig(&thisProxyConfigRecord)
  255. //Update utm if exists
  256. if uptimeMonitor != nil {
  257. uptimeMonitor.Config.Targets = GetUptimeTargetsFromReverseProxyRules(dynamicProxyRouter)
  258. uptimeMonitor.CleanRecords()
  259. }
  260. utils.SendOK(w)
  261. }
  262. /*
  263. ReverseProxyHandleEditEndpoint handles proxy endpoint edit
  264. This endpoint do not handle
  265. basic auth credential update. The credential
  266. will be loaded from old config and reused
  267. */
  268. func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
  269. eptype, err := utils.PostPara(r, "type") //Support root, vdir and subd
  270. if err != nil {
  271. utils.SendErrorResponse(w, "type not defined")
  272. return
  273. }
  274. rootNameOrMatchingDomain, err := utils.PostPara(r, "rootname")
  275. if err != nil {
  276. utils.SendErrorResponse(w, "Target proxy rule not defined")
  277. return
  278. }
  279. endpoint, err := utils.PostPara(r, "ep")
  280. if err != nil {
  281. utils.SendErrorResponse(w, "endpoint not defined")
  282. return
  283. }
  284. tls, _ := utils.PostPara(r, "tls")
  285. if tls == "" {
  286. tls = "false"
  287. }
  288. useTLS := (tls == "true")
  289. stv, _ := utils.PostPara(r, "tlsval")
  290. if stv == "" {
  291. stv = "false"
  292. }
  293. skipTlsValidation := (stv == "true")
  294. rba, _ := utils.PostPara(r, "bauth")
  295. if rba == "" {
  296. rba = "false"
  297. }
  298. requireBasicAuth := (rba == "true")
  299. //Load the previous basic auth credentials from current proxy rules
  300. targetProxyEntry, err := dynamicProxyRouter.LoadProxy(eptype, rootNameOrMatchingDomain)
  301. if err != nil {
  302. utils.SendErrorResponse(w, "Target proxy config not found or could not be loaded")
  303. return
  304. }
  305. if eptype == "vdir" {
  306. thisOption := dynamicproxy.VdirOptions{
  307. RootName: targetProxyEntry.RootOrMatchingDomain,
  308. Domain: endpoint,
  309. RequireTLS: useTLS,
  310. SkipCertValidations: skipTlsValidation,
  311. RequireBasicAuth: requireBasicAuth,
  312. BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
  313. }
  314. dynamicProxyRouter.RemoveProxy("vdir", thisOption.RootName)
  315. dynamicProxyRouter.AddVirtualDirectoryProxyService(&thisOption)
  316. } else if eptype == "subd" {
  317. thisOption := dynamicproxy.SubdOptions{
  318. MatchingDomain: targetProxyEntry.RootOrMatchingDomain,
  319. Domain: endpoint,
  320. RequireTLS: useTLS,
  321. SkipCertValidations: skipTlsValidation,
  322. RequireBasicAuth: requireBasicAuth,
  323. BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
  324. }
  325. dynamicProxyRouter.RemoveProxy("subd", thisOption.MatchingDomain)
  326. dynamicProxyRouter.AddSubdomainRoutingService(&thisOption)
  327. }
  328. //Save it to file
  329. thisProxyConfigRecord := Record{
  330. ProxyType: eptype,
  331. Rootname: targetProxyEntry.RootOrMatchingDomain,
  332. ProxyTarget: endpoint,
  333. UseTLS: useTLS,
  334. SkipTlsValidation: skipTlsValidation,
  335. RequireBasicAuth: requireBasicAuth,
  336. BasicAuthCredentials: targetProxyEntry.BasicAuthCredentials,
  337. }
  338. SaveReverseProxyConfig(&thisProxyConfigRecord)
  339. utils.SendOK(w)
  340. }
  341. func DeleteProxyEndpoint(w http.ResponseWriter, r *http.Request) {
  342. ep, err := utils.GetPara(r, "ep")
  343. if err != nil {
  344. utils.SendErrorResponse(w, "Invalid ep given")
  345. return
  346. }
  347. ptype, err := utils.PostPara(r, "ptype")
  348. if err != nil {
  349. utils.SendErrorResponse(w, "Invalid ptype given")
  350. return
  351. }
  352. err = dynamicProxyRouter.RemoveProxy(ptype, ep)
  353. if err != nil {
  354. utils.SendErrorResponse(w, err.Error())
  355. return
  356. }
  357. RemoveReverseProxyConfig(ep)
  358. //Update utm if exists
  359. if uptimeMonitor != nil {
  360. uptimeMonitor.Config.Targets = GetUptimeTargetsFromReverseProxyRules(dynamicProxyRouter)
  361. uptimeMonitor.CleanRecords()
  362. }
  363. utils.SendOK(w)
  364. }
  365. /*
  366. Handle update request for basic auth credential
  367. Require paramter: ep (Endpoint) and pytype (proxy Type)
  368. if request with GET, the handler will return current credentials
  369. on this endpoint by its username
  370. if request is POST, the handler will write the results to proxy config
  371. */
  372. func UpdateProxyBasicAuthCredentials(w http.ResponseWriter, r *http.Request) {
  373. if r.Method == http.MethodGet {
  374. ep, err := utils.GetPara(r, "ep")
  375. if err != nil {
  376. utils.SendErrorResponse(w, "Invalid ep given")
  377. return
  378. }
  379. ptype, err := utils.GetPara(r, "ptype")
  380. if err != nil {
  381. utils.SendErrorResponse(w, "Invalid ptype given")
  382. return
  383. }
  384. //Load the target proxy object from router
  385. targetProxy, err := dynamicProxyRouter.LoadProxy(ptype, ep)
  386. if err != nil {
  387. utils.SendErrorResponse(w, err.Error())
  388. return
  389. }
  390. usernames := []string{}
  391. for _, cred := range targetProxy.BasicAuthCredentials {
  392. usernames = append(usernames, cred.Username)
  393. }
  394. js, _ := json.Marshal(usernames)
  395. utils.SendJSONResponse(w, string(js))
  396. } else if r.Method == http.MethodPost {
  397. //Write to target
  398. ep, err := utils.PostPara(r, "ep")
  399. if err != nil {
  400. utils.SendErrorResponse(w, "Invalid ep given")
  401. return
  402. }
  403. ptype, err := utils.PostPara(r, "ptype")
  404. if err != nil {
  405. utils.SendErrorResponse(w, "Invalid ptype given")
  406. return
  407. }
  408. if ptype != "vdir" && ptype != "subd" {
  409. utils.SendErrorResponse(w, "Invalid ptype given")
  410. return
  411. }
  412. creds, err := utils.PostPara(r, "creds")
  413. if err != nil {
  414. utils.SendErrorResponse(w, "Invalid ptype given")
  415. return
  416. }
  417. //Load the target proxy object from router
  418. targetProxy, err := dynamicProxyRouter.LoadProxy(ptype, ep)
  419. if err != nil {
  420. utils.SendErrorResponse(w, err.Error())
  421. return
  422. }
  423. //Try to marshal the content of creds into the suitable structure
  424. newCredentials := []*dynamicproxy.BasicAuthUnhashedCredentials{}
  425. err = json.Unmarshal([]byte(creds), &newCredentials)
  426. if err != nil {
  427. utils.SendErrorResponse(w, "Malformed credential data")
  428. return
  429. }
  430. //Merge the credentials into the original config
  431. //If a new username exists in old config with no pw given, keep the old pw hash
  432. //If a new username is found with new password, hash it and push to credential slice
  433. mergedCredentials := []*dynamicproxy.BasicAuthCredentials{}
  434. for _, credential := range newCredentials {
  435. if credential.Password == "" {
  436. //Check if exists in the old credential files
  437. keepUnchange := false
  438. for _, oldCredEntry := range targetProxy.BasicAuthCredentials {
  439. if oldCredEntry.Username == credential.Username {
  440. //Exists! Reuse the old hash
  441. mergedCredentials = append(mergedCredentials, &dynamicproxy.BasicAuthCredentials{
  442. Username: oldCredEntry.Username,
  443. PasswordHash: oldCredEntry.PasswordHash,
  444. })
  445. keepUnchange = true
  446. }
  447. }
  448. if !keepUnchange {
  449. //This is a new username with no pw given
  450. utils.SendErrorResponse(w, "Access password for "+credential.Username+" is empty!")
  451. return
  452. }
  453. } else {
  454. //This username have given password
  455. mergedCredentials = append(mergedCredentials, &dynamicproxy.BasicAuthCredentials{
  456. Username: credential.Username,
  457. PasswordHash: auth.Hash(credential.Password),
  458. })
  459. }
  460. }
  461. targetProxy.BasicAuthCredentials = mergedCredentials
  462. //Save it to file
  463. thisProxyConfigRecord := Record{
  464. ProxyType: ptype,
  465. Rootname: targetProxy.RootOrMatchingDomain,
  466. ProxyTarget: targetProxy.Domain,
  467. UseTLS: targetProxy.RequireTLS,
  468. SkipTlsValidation: targetProxy.SkipCertValidations,
  469. RequireBasicAuth: targetProxy.RequireBasicAuth,
  470. BasicAuthCredentials: targetProxy.BasicAuthCredentials,
  471. }
  472. SaveReverseProxyConfig(&thisProxyConfigRecord)
  473. //Replace runtime configuration
  474. dynamicProxyRouter.SaveProxy(ptype, ep, targetProxy)
  475. utils.SendOK(w)
  476. } else {
  477. http.Error(w, "invalid usage", http.StatusMethodNotAllowed)
  478. }
  479. }
  480. func ReverseProxyStatus(w http.ResponseWriter, r *http.Request) {
  481. js, _ := json.Marshal(dynamicProxyRouter)
  482. utils.SendJSONResponse(w, string(js))
  483. }
  484. func ReverseProxyList(w http.ResponseWriter, r *http.Request) {
  485. eptype, err := utils.PostPara(r, "type") //Support root, vdir and subd
  486. if err != nil {
  487. utils.SendErrorResponse(w, "type not defined")
  488. return
  489. }
  490. if eptype == "vdir" {
  491. results := []*dynamicproxy.ProxyEndpoint{}
  492. dynamicProxyRouter.ProxyEndpoints.Range(func(key, value interface{}) bool {
  493. results = append(results, value.(*dynamicproxy.ProxyEndpoint))
  494. return true
  495. })
  496. sort.Slice(results, func(i, j int) bool {
  497. return results[i].Domain < results[j].Domain
  498. })
  499. js, _ := json.Marshal(results)
  500. utils.SendJSONResponse(w, string(js))
  501. } else if eptype == "subd" {
  502. results := []*dynamicproxy.ProxyEndpoint{}
  503. dynamicProxyRouter.SubdomainEndpoint.Range(func(key, value interface{}) bool {
  504. results = append(results, value.(*dynamicproxy.ProxyEndpoint))
  505. return true
  506. })
  507. sort.Slice(results, func(i, j int) bool {
  508. return results[i].RootOrMatchingDomain < results[j].RootOrMatchingDomain
  509. })
  510. js, _ := json.Marshal(results)
  511. utils.SendJSONResponse(w, string(js))
  512. } else if eptype == "root" {
  513. js, _ := json.Marshal(dynamicProxyRouter.Root)
  514. utils.SendJSONResponse(w, string(js))
  515. } else {
  516. utils.SendErrorResponse(w, "Invalid type given")
  517. }
  518. }
  519. // Handle https redirect
  520. func HandleUpdateHttpsRedirect(w http.ResponseWriter, r *http.Request) {
  521. useRedirect, err := utils.GetPara(r, "set")
  522. if err != nil {
  523. currentRedirectToHttps := false
  524. //Load the current status
  525. err = sysdb.Read("settings", "redirect", &currentRedirectToHttps)
  526. if err != nil {
  527. utils.SendErrorResponse(w, err.Error())
  528. return
  529. }
  530. js, _ := json.Marshal(currentRedirectToHttps)
  531. utils.SendJSONResponse(w, string(js))
  532. } else {
  533. if dynamicProxyRouter.Option.Port == 80 {
  534. utils.SendErrorResponse(w, "This option is not available when listening on port 80")
  535. return
  536. }
  537. if useRedirect == "true" {
  538. sysdb.Write("settings", "redirect", true)
  539. log.Println("Updating force HTTPS redirection to true")
  540. dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(true)
  541. } else if useRedirect == "false" {
  542. sysdb.Write("settings", "redirect", false)
  543. log.Println("Updating force HTTPS redirection to false")
  544. dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(false)
  545. }
  546. utils.SendOK(w)
  547. }
  548. }
  549. // Handle checking if the current user is accessing via the reverse proxied interface
  550. // Of the management interface.
  551. func HandleManagementProxyCheck(w http.ResponseWriter, r *http.Request) {
  552. isProxied := dynamicProxyRouter.IsProxiedSubdomain(r)
  553. js, _ := json.Marshal(isProxied)
  554. utils.SendJSONResponse(w, string(js))
  555. }
  556. // Handle incoming port set. Change the current proxy incoming port
  557. func HandleIncomingPortSet(w http.ResponseWriter, r *http.Request) {
  558. newIncomingPort, err := utils.PostPara(r, "incoming")
  559. if err != nil {
  560. utils.SendErrorResponse(w, "invalid incoming port given")
  561. return
  562. }
  563. newIncomingPortInt, err := strconv.Atoi(newIncomingPort)
  564. if err != nil {
  565. utils.SendErrorResponse(w, "Invalid incoming port given")
  566. return
  567. }
  568. //Check if it is identical as proxy root (recursion!)
  569. if dynamicProxyRouter.Root == nil || dynamicProxyRouter.Root.Domain == "" {
  570. //Check if proxy root is set before checking recursive listen
  571. //Fixing issue #43
  572. utils.SendErrorResponse(w, "Set Proxy Root before changing inbound port")
  573. return
  574. }
  575. proxyRoot := strings.TrimSuffix(dynamicProxyRouter.Root.Domain, "/")
  576. if strings.HasPrefix(proxyRoot, "localhost:"+strconv.Itoa(newIncomingPortInt)) || strings.HasPrefix(proxyRoot, "127.0.0.1:"+strconv.Itoa(newIncomingPortInt)) {
  577. //Listening port is same as proxy root
  578. //Not allow recursive settings
  579. utils.SendErrorResponse(w, "Recursive listening port! Check your proxy root settings.")
  580. return
  581. }
  582. //Stop and change the setting of the reverse proxy service
  583. if dynamicProxyRouter.Running {
  584. dynamicProxyRouter.StopProxyService()
  585. dynamicProxyRouter.Option.Port = newIncomingPortInt
  586. dynamicProxyRouter.StartProxyService()
  587. } else {
  588. //Only change setting but not starting the proxy service
  589. dynamicProxyRouter.Option.Port = newIncomingPortInt
  590. }
  591. sysdb.Write("settings", "inbound", newIncomingPortInt)
  592. utils.SendOK(w)
  593. }