reverseproxy.go 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321
  1. package main
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "path/filepath"
  6. "sort"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "imuslab.com/zoraxy/mod/auth"
  11. "imuslab.com/zoraxy/mod/dynamicproxy"
  12. "imuslab.com/zoraxy/mod/dynamicproxy/permissionpolicy"
  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. /*
  22. Load Reverse Proxy Global Settings
  23. */
  24. inboundPort := 80
  25. if sysdb.KeyExists("settings", "inbound") {
  26. sysdb.Read("settings", "inbound", &inboundPort)
  27. SystemWideLogger.Println("Serving inbound port ", inboundPort)
  28. } else {
  29. SystemWideLogger.Println("Inbound port not set. Using default (80)")
  30. }
  31. useTls := false
  32. sysdb.Read("settings", "usetls", &useTls)
  33. if useTls {
  34. SystemWideLogger.Println("TLS mode enabled. Serving proxxy request with TLS")
  35. } else {
  36. SystemWideLogger.Println("TLS mode disabled. Serving proxy request with plain http")
  37. }
  38. forceLatestTLSVersion := false
  39. sysdb.Read("settings", "forceLatestTLS", &forceLatestTLSVersion)
  40. if forceLatestTLSVersion {
  41. SystemWideLogger.Println("Force latest TLS mode enabled. Minimum TLS LS version is set to v1.2")
  42. } else {
  43. SystemWideLogger.Println("Force latest TLS mode disabled. Minimum TLS version is set to v1.0")
  44. }
  45. developmentMode := false
  46. sysdb.Read("settings", "devMode", &developmentMode)
  47. if useTls {
  48. SystemWideLogger.Println("Development mode enabled. Using no-store Cache Control policy")
  49. } else {
  50. SystemWideLogger.Println("Development mode disabled. Proxying with default Cache Control policy")
  51. }
  52. listenOnPort80 := false
  53. sysdb.Read("settings", "listenP80", &listenOnPort80)
  54. if listenOnPort80 {
  55. SystemWideLogger.Println("Port 80 listener enabled")
  56. } else {
  57. SystemWideLogger.Println("Port 80 listener disabled")
  58. }
  59. forceHttpsRedirect := false
  60. sysdb.Read("settings", "redirect", &forceHttpsRedirect)
  61. if forceHttpsRedirect {
  62. SystemWideLogger.Println("Force HTTPS mode enabled")
  63. //Port 80 listener must be enabled to perform http -> https redirect
  64. listenOnPort80 = true
  65. } else {
  66. SystemWideLogger.Println("Force HTTPS mode disabled")
  67. }
  68. /*
  69. Create a new proxy object
  70. The DynamicProxy is the parent of all reverse proxy handlers,
  71. use for managemening and provide functions to access proxy handlers
  72. */
  73. dprouter, err := dynamicproxy.NewDynamicProxy(dynamicproxy.RouterOption{
  74. HostUUID: nodeUUID,
  75. HostVersion: version,
  76. Port: inboundPort,
  77. UseTls: useTls,
  78. ForceTLSLatest: forceLatestTLSVersion,
  79. NoCache: developmentMode,
  80. ListenOnPort80: listenOnPort80,
  81. ForceHttpsRedirect: forceHttpsRedirect,
  82. TlsManager: tlsCertManager,
  83. RedirectRuleTable: redirectTable,
  84. GeodbStore: geodbStore,
  85. StatisticCollector: statisticCollector,
  86. WebDirectory: *staticWebServerRoot,
  87. AccessController: accessController,
  88. })
  89. if err != nil {
  90. SystemWideLogger.PrintAndLog("Proxy", "Unable to create dynamic proxy router", err)
  91. return
  92. }
  93. dynamicProxyRouter = dprouter
  94. /*
  95. Load all conf from files
  96. */
  97. confs, _ := filepath.Glob("./conf/proxy/*.config")
  98. for _, conf := range confs {
  99. err := LoadReverseProxyConfig(conf)
  100. if err != nil {
  101. SystemWideLogger.PrintAndLog("Proxy", "Failed to load config file: "+filepath.Base(conf), err)
  102. return
  103. }
  104. }
  105. if dynamicProxyRouter.Root == nil {
  106. //Root config not set (new deployment?), use internal static web server as root
  107. defaultRootRouter, err := GetDefaultRootConfig()
  108. if err != nil {
  109. SystemWideLogger.PrintAndLog("Proxy", "Failed to generate default root routing", err)
  110. return
  111. }
  112. dynamicProxyRouter.SetProxyRouteAsRoot(defaultRootRouter)
  113. }
  114. //Start Service
  115. //Not sure why but delay must be added if you have another
  116. //reverse proxy server in front of this service
  117. time.Sleep(300 * time.Millisecond)
  118. dynamicProxyRouter.StartProxyService()
  119. SystemWideLogger.Println("Dynamic Reverse Proxy service started")
  120. //Add all proxy services to uptime monitor
  121. //Create a uptime monitor service
  122. go func() {
  123. //This must be done in go routine to prevent blocking on system startup
  124. uptimeMonitor, _ = uptime.NewUptimeMonitor(&uptime.Config{
  125. Targets: GetUptimeTargetsFromReverseProxyRules(dynamicProxyRouter),
  126. Interval: 300, //5 minutes
  127. MaxRecordsStore: 288, //1 day
  128. })
  129. SystemWideLogger.Println("Uptime Monitor background service started")
  130. }()
  131. }
  132. func ReverseProxyHandleOnOff(w http.ResponseWriter, r *http.Request) {
  133. enable, _ := utils.PostPara(r, "enable") //Support root, vdir and subd
  134. if enable == "true" {
  135. err := dynamicProxyRouter.StartProxyService()
  136. if err != nil {
  137. utils.SendErrorResponse(w, err.Error())
  138. return
  139. }
  140. } else {
  141. //Check if it is loopback
  142. if dynamicProxyRouter.IsProxiedSubdomain(r) {
  143. //Loopback routing. Turning it off will make the user lost control
  144. //of the whole system. Do not allow shutdown
  145. utils.SendErrorResponse(w, "Unable to shutdown in loopback rp mode. Remove proxy rules for management interface and retry.")
  146. return
  147. }
  148. err := dynamicProxyRouter.StopProxyService()
  149. if err != nil {
  150. utils.SendErrorResponse(w, err.Error())
  151. return
  152. }
  153. }
  154. utils.SendOK(w)
  155. }
  156. func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
  157. eptype, err := utils.PostPara(r, "type") //Support root and host
  158. if err != nil {
  159. utils.SendErrorResponse(w, "type not defined")
  160. return
  161. }
  162. endpoint, err := utils.PostPara(r, "ep")
  163. if err != nil {
  164. utils.SendErrorResponse(w, "endpoint not defined")
  165. return
  166. }
  167. tls, _ := utils.PostPara(r, "tls")
  168. if tls == "" {
  169. tls = "false"
  170. }
  171. useTLS := (tls == "true")
  172. //Bypass global TLS value / allow direct access from port 80?
  173. bypassGlobalTLS, _ := utils.PostPara(r, "bypassGlobalTLS")
  174. if bypassGlobalTLS == "" {
  175. bypassGlobalTLS = "false"
  176. }
  177. useBypassGlobalTLS := bypassGlobalTLS == "true"
  178. //Enable TLS validation?
  179. stv, _ := utils.PostPara(r, "tlsval")
  180. if stv == "" {
  181. stv = "false"
  182. }
  183. skipTlsValidation := (stv == "true")
  184. //Get access rule ID
  185. accessRuleID, _ := utils.PostPara(r, "access")
  186. if accessRuleID == "" {
  187. accessRuleID = "default"
  188. }
  189. if !accessController.AccessRuleExists(accessRuleID) {
  190. utils.SendErrorResponse(w, "invalid access rule ID selected")
  191. return
  192. }
  193. //Require basic auth?
  194. rba, _ := utils.PostPara(r, "bauth")
  195. if rba == "" {
  196. rba = "false"
  197. }
  198. requireBasicAuth := (rba == "true")
  199. // Require Rate Limiting?
  200. rl, _ := utils.PostPara(r, "rate")
  201. if rl == "" {
  202. rl = "false"
  203. }
  204. requireRateLimit := (rl == "true")
  205. rlnum, _ := utils.PostPara(r, "ratenum")
  206. if rlnum == "" {
  207. rlnum = "0"
  208. }
  209. proxyRateLimit, err := strconv.ParseInt(rlnum, 10, 64)
  210. if err != nil {
  211. utils.SendErrorResponse(w, "invalid rate limit number")
  212. return
  213. }
  214. if proxyRateLimit <= 0 {
  215. utils.SendErrorResponse(w, "rate limit number must be greater than 0")
  216. return
  217. }
  218. // Bypass WebSocket Origin Check
  219. strbpwsorg, _ := utils.PostPara(r, "bpwsorg")
  220. if strbpwsorg == "" {
  221. strbpwsorg = "false"
  222. }
  223. bypassWebsocketOriginCheck := (strbpwsorg == "true")
  224. //Prase the basic auth to correct structure
  225. cred, _ := utils.PostPara(r, "cred")
  226. basicAuthCredentials := []*dynamicproxy.BasicAuthCredentials{}
  227. if requireBasicAuth {
  228. preProcessCredentials := []*dynamicproxy.BasicAuthUnhashedCredentials{}
  229. err = json.Unmarshal([]byte(cred), &preProcessCredentials)
  230. if err != nil {
  231. utils.SendErrorResponse(w, "invalid user credentials")
  232. return
  233. }
  234. //Check if there are empty password credentials
  235. for _, credObj := range preProcessCredentials {
  236. if strings.TrimSpace(credObj.Password) == "" {
  237. utils.SendErrorResponse(w, credObj.Username+" has empty password")
  238. return
  239. }
  240. }
  241. //Convert and hash the passwords
  242. for _, credObj := range preProcessCredentials {
  243. basicAuthCredentials = append(basicAuthCredentials, &dynamicproxy.BasicAuthCredentials{
  244. Username: credObj.Username,
  245. PasswordHash: auth.Hash(credObj.Password),
  246. })
  247. }
  248. }
  249. var proxyEndpointCreated *dynamicproxy.ProxyEndpoint
  250. if eptype == "host" {
  251. rootOrMatchingDomain, err := utils.PostPara(r, "rootname")
  252. if err != nil {
  253. utils.SendErrorResponse(w, "hostname not defined")
  254. return
  255. }
  256. rootOrMatchingDomain = strings.TrimSpace(rootOrMatchingDomain)
  257. //Check if it contains ",", if yes, split the remainings as alias
  258. aliasHostnames := []string{}
  259. if strings.Contains(rootOrMatchingDomain, ",") {
  260. matchingDomains := strings.Split(rootOrMatchingDomain, ",")
  261. if len(matchingDomains) > 1 {
  262. rootOrMatchingDomain = matchingDomains[0]
  263. for _, aliasHostname := range matchingDomains[1:] {
  264. //Filter out any space
  265. aliasHostnames = append(aliasHostnames, strings.TrimSpace(aliasHostname))
  266. }
  267. }
  268. }
  269. //Generate a proxy endpoint object
  270. thisProxyEndpoint := dynamicproxy.ProxyEndpoint{
  271. //I/O
  272. ProxyType: dynamicproxy.ProxyType_Host,
  273. RootOrMatchingDomain: rootOrMatchingDomain,
  274. MatchingDomainAlias: aliasHostnames,
  275. Domain: endpoint,
  276. //TLS
  277. RequireTLS: useTLS,
  278. BypassGlobalTLS: useBypassGlobalTLS,
  279. SkipCertValidations: skipTlsValidation,
  280. SkipWebSocketOriginCheck: bypassWebsocketOriginCheck,
  281. AccessFilterUUID: accessRuleID,
  282. //VDir
  283. VirtualDirectories: []*dynamicproxy.VirtualDirectoryEndpoint{},
  284. //Custom headers
  285. UserDefinedHeaders: []*dynamicproxy.UserDefinedHeader{},
  286. //Auth
  287. RequireBasicAuth: requireBasicAuth,
  288. BasicAuthCredentials: basicAuthCredentials,
  289. BasicAuthExceptionRules: []*dynamicproxy.BasicAuthExceptionRule{},
  290. DefaultSiteOption: 0,
  291. DefaultSiteValue: "",
  292. // Rate Limit
  293. RequireRateLimit: requireRateLimit,
  294. RateLimit: proxyRateLimit,
  295. }
  296. preparedEndpoint, err := dynamicProxyRouter.PrepareProxyRoute(&thisProxyEndpoint)
  297. if err != nil {
  298. utils.SendErrorResponse(w, "unable to prepare proxy route to target endpoint: "+err.Error())
  299. return
  300. }
  301. dynamicProxyRouter.AddProxyRouteToRuntime(preparedEndpoint)
  302. proxyEndpointCreated = &thisProxyEndpoint
  303. } else if eptype == "root" {
  304. //Get the default site options and target
  305. dsOptString, err := utils.PostPara(r, "defaultSiteOpt")
  306. if err != nil {
  307. utils.SendErrorResponse(w, "default site action not defined")
  308. return
  309. }
  310. var defaultSiteOption int = 1
  311. opt, err := strconv.Atoi(dsOptString)
  312. if err != nil {
  313. utils.SendErrorResponse(w, "invalid default site option")
  314. return
  315. }
  316. defaultSiteOption = opt
  317. dsVal, err := utils.PostPara(r, "defaultSiteVal")
  318. if err != nil && (defaultSiteOption == 1 || defaultSiteOption == 2) {
  319. //Reverse proxy or redirect, must require value to be set
  320. utils.SendErrorResponse(w, "target not defined")
  321. return
  322. }
  323. //Write the root options to file
  324. rootRoutingEndpoint := dynamicproxy.ProxyEndpoint{
  325. ProxyType: dynamicproxy.ProxyType_Root,
  326. RootOrMatchingDomain: "/",
  327. Domain: endpoint,
  328. RequireTLS: useTLS,
  329. BypassGlobalTLS: false,
  330. SkipCertValidations: false,
  331. SkipWebSocketOriginCheck: true,
  332. DefaultSiteOption: defaultSiteOption,
  333. DefaultSiteValue: dsVal,
  334. }
  335. preparedRootProxyRoute, err := dynamicProxyRouter.PrepareProxyRoute(&rootRoutingEndpoint)
  336. if err != nil {
  337. utils.SendErrorResponse(w, "unable to prepare root routing: "+err.Error())
  338. return
  339. }
  340. dynamicProxyRouter.SetProxyRouteAsRoot(preparedRootProxyRoute)
  341. proxyEndpointCreated = &rootRoutingEndpoint
  342. } else {
  343. //Invalid eptype
  344. utils.SendErrorResponse(w, "invalid endpoint type")
  345. return
  346. }
  347. //Save the config to file
  348. err = SaveReverseProxyConfig(proxyEndpointCreated)
  349. if err != nil {
  350. SystemWideLogger.PrintAndLog("Proxy", "Unable to save new proxy rule to file", err)
  351. return
  352. }
  353. //Update utm if exists
  354. UpdateUptimeMonitorTargets()
  355. utils.SendOK(w)
  356. }
  357. /*
  358. ReverseProxyHandleEditEndpoint handles proxy endpoint edit
  359. (host only, for root use Default Site page to edit)
  360. This endpoint do not handle basic auth credential update.
  361. The credential will be loaded from old config and reused
  362. */
  363. func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
  364. rootNameOrMatchingDomain, err := utils.PostPara(r, "rootname")
  365. if err != nil {
  366. utils.SendErrorResponse(w, "Target proxy rule not defined")
  367. return
  368. }
  369. endpoint, err := utils.PostPara(r, "ep")
  370. if err != nil {
  371. utils.SendErrorResponse(w, "endpoint not defined")
  372. return
  373. }
  374. tls, _ := utils.PostPara(r, "tls")
  375. if tls == "" {
  376. tls = "false"
  377. }
  378. useTLS := (tls == "true")
  379. stv, _ := utils.PostPara(r, "tlsval")
  380. if stv == "" {
  381. stv = "false"
  382. }
  383. skipTlsValidation := (stv == "true")
  384. //Load bypass TLS option
  385. bpgtls, _ := utils.PostPara(r, "bpgtls")
  386. if bpgtls == "" {
  387. bpgtls = "false"
  388. }
  389. bypassGlobalTLS := (bpgtls == "true")
  390. // Basic Auth
  391. rba, _ := utils.PostPara(r, "bauth")
  392. if rba == "" {
  393. rba = "false"
  394. }
  395. requireBasicAuth := (rba == "true")
  396. // Rate Limiting?
  397. rl, _ := utils.PostPara(r, "rate")
  398. if rl == "" {
  399. rl = "false"
  400. }
  401. requireRateLimit := (rl == "true")
  402. rlnum, _ := utils.PostPara(r, "ratenum")
  403. if rlnum == "" {
  404. rlnum = "0"
  405. }
  406. proxyRateLimit, err := strconv.ParseInt(rlnum, 10, 64)
  407. if err != nil {
  408. utils.SendErrorResponse(w, "invalid rate limit number")
  409. return
  410. }
  411. if proxyRateLimit <= 0 {
  412. utils.SendErrorResponse(w, "rate limit number must be greater than 0")
  413. return
  414. }
  415. // Bypass WebSocket Origin Check
  416. strbpwsorg, _ := utils.PostPara(r, "bpwsorg")
  417. if strbpwsorg == "" {
  418. strbpwsorg = "false"
  419. }
  420. bypassWebsocketOriginCheck := (strbpwsorg == "true")
  421. //Load the previous basic auth credentials from current proxy rules
  422. targetProxyEntry, err := dynamicProxyRouter.LoadProxy(rootNameOrMatchingDomain)
  423. if err != nil {
  424. utils.SendErrorResponse(w, "Target proxy config not found or could not be loaded")
  425. return
  426. }
  427. //Generate a new proxyEndpoint from the new config
  428. newProxyEndpoint := dynamicproxy.CopyEndpoint(targetProxyEntry)
  429. newProxyEndpoint.Domain = endpoint
  430. newProxyEndpoint.RequireTLS = useTLS
  431. newProxyEndpoint.BypassGlobalTLS = bypassGlobalTLS
  432. newProxyEndpoint.SkipCertValidations = skipTlsValidation
  433. newProxyEndpoint.RequireBasicAuth = requireBasicAuth
  434. newProxyEndpoint.RequireRateLimit = requireRateLimit
  435. newProxyEndpoint.RateLimit = proxyRateLimit
  436. newProxyEndpoint.SkipWebSocketOriginCheck = bypassWebsocketOriginCheck
  437. //Prepare to replace the current routing rule
  438. readyRoutingRule, err := dynamicProxyRouter.PrepareProxyRoute(newProxyEndpoint)
  439. if err != nil {
  440. utils.SendErrorResponse(w, err.Error())
  441. return
  442. }
  443. targetProxyEntry.Remove()
  444. dynamicProxyRouter.AddProxyRouteToRuntime(readyRoutingRule)
  445. //Save it to file
  446. SaveReverseProxyConfig(newProxyEndpoint)
  447. //Update uptime monitor
  448. UpdateUptimeMonitorTargets()
  449. utils.SendOK(w)
  450. }
  451. func ReverseProxyHandleAlias(w http.ResponseWriter, r *http.Request) {
  452. rootNameOrMatchingDomain, err := utils.PostPara(r, "ep")
  453. if err != nil {
  454. utils.SendErrorResponse(w, "Invalid ep given")
  455. return
  456. }
  457. //No need to check for type as root (/) can be set to default route
  458. //and hence, you will not need alias
  459. //Load the previous alias from current proxy rules
  460. targetProxyEntry, err := dynamicProxyRouter.LoadProxy(rootNameOrMatchingDomain)
  461. if err != nil {
  462. utils.SendErrorResponse(w, "Target proxy config not found or could not be loaded")
  463. return
  464. }
  465. newAliasJSON, err := utils.PostPara(r, "alias")
  466. if err != nil {
  467. //No new set of alias given
  468. utils.SendErrorResponse(w, "new alias not given")
  469. return
  470. }
  471. //Write new alias to runtime and file
  472. newAlias := []string{}
  473. err = json.Unmarshal([]byte(newAliasJSON), &newAlias)
  474. if err != nil {
  475. SystemWideLogger.PrintAndLog("Proxy", "Unable to parse new alias list", err)
  476. utils.SendErrorResponse(w, "Invalid alias list given")
  477. return
  478. }
  479. //Set the current alias
  480. newProxyEndpoint := dynamicproxy.CopyEndpoint(targetProxyEntry)
  481. newProxyEndpoint.MatchingDomainAlias = newAlias
  482. // Prepare to replace the current routing rule
  483. readyRoutingRule, err := dynamicProxyRouter.PrepareProxyRoute(newProxyEndpoint)
  484. if err != nil {
  485. utils.SendErrorResponse(w, err.Error())
  486. return
  487. }
  488. targetProxyEntry.Remove()
  489. dynamicProxyRouter.AddProxyRouteToRuntime(readyRoutingRule)
  490. // Save it to file
  491. err = SaveReverseProxyConfig(newProxyEndpoint)
  492. if err != nil {
  493. utils.SendErrorResponse(w, "Alias update failed")
  494. SystemWideLogger.PrintAndLog("Proxy", "Unable to save alias update", err)
  495. }
  496. utils.SendOK(w)
  497. }
  498. func DeleteProxyEndpoint(w http.ResponseWriter, r *http.Request) {
  499. ep, err := utils.GetPara(r, "ep")
  500. if err != nil {
  501. utils.SendErrorResponse(w, "Invalid ep given")
  502. return
  503. }
  504. //Remove the config from runtime
  505. err = dynamicProxyRouter.RemoveProxyEndpointByRootname(ep)
  506. if err != nil {
  507. utils.SendErrorResponse(w, err.Error())
  508. return
  509. }
  510. //Remove the config from file
  511. err = RemoveReverseProxyConfig(ep)
  512. if err != nil {
  513. utils.SendErrorResponse(w, err.Error())
  514. return
  515. }
  516. //Update utm if exists
  517. if uptimeMonitor != nil {
  518. uptimeMonitor.Config.Targets = GetUptimeTargetsFromReverseProxyRules(dynamicProxyRouter)
  519. uptimeMonitor.CleanRecords()
  520. }
  521. //Update uptime monitor
  522. UpdateUptimeMonitorTargets()
  523. utils.SendOK(w)
  524. }
  525. /*
  526. Handle update request for basic auth credential
  527. Require paramter: ep (Endpoint) and pytype (proxy Type)
  528. if request with GET, the handler will return current credentials
  529. on this endpoint by its username
  530. if request is POST, the handler will write the results to proxy config
  531. */
  532. func UpdateProxyBasicAuthCredentials(w http.ResponseWriter, r *http.Request) {
  533. if r.Method == http.MethodGet {
  534. ep, err := utils.GetPara(r, "ep")
  535. if err != nil {
  536. utils.SendErrorResponse(w, "Invalid ep given")
  537. return
  538. }
  539. //Load the target proxy object from router
  540. targetProxy, err := dynamicProxyRouter.LoadProxy(ep)
  541. if err != nil {
  542. utils.SendErrorResponse(w, err.Error())
  543. return
  544. }
  545. usernames := []string{}
  546. for _, cred := range targetProxy.BasicAuthCredentials {
  547. usernames = append(usernames, cred.Username)
  548. }
  549. js, _ := json.Marshal(usernames)
  550. utils.SendJSONResponse(w, string(js))
  551. } else if r.Method == http.MethodPost {
  552. //Write to target
  553. ep, err := utils.PostPara(r, "ep")
  554. if err != nil {
  555. utils.SendErrorResponse(w, "Invalid ep given")
  556. return
  557. }
  558. creds, err := utils.PostPara(r, "creds")
  559. if err != nil {
  560. utils.SendErrorResponse(w, "Invalid ptype given")
  561. return
  562. }
  563. //Load the target proxy object from router
  564. targetProxy, err := dynamicProxyRouter.LoadProxy(ep)
  565. if err != nil {
  566. utils.SendErrorResponse(w, err.Error())
  567. return
  568. }
  569. //Try to marshal the content of creds into the suitable structure
  570. newCredentials := []*dynamicproxy.BasicAuthUnhashedCredentials{}
  571. err = json.Unmarshal([]byte(creds), &newCredentials)
  572. if err != nil {
  573. utils.SendErrorResponse(w, "Malformed credential data")
  574. return
  575. }
  576. //Merge the credentials into the original config
  577. //If a new username exists in old config with no pw given, keep the old pw hash
  578. //If a new username is found with new password, hash it and push to credential slice
  579. mergedCredentials := []*dynamicproxy.BasicAuthCredentials{}
  580. for _, credential := range newCredentials {
  581. if credential.Password == "" {
  582. //Check if exists in the old credential files
  583. keepUnchange := false
  584. for _, oldCredEntry := range targetProxy.BasicAuthCredentials {
  585. if oldCredEntry.Username == credential.Username {
  586. //Exists! Reuse the old hash
  587. mergedCredentials = append(mergedCredentials, &dynamicproxy.BasicAuthCredentials{
  588. Username: oldCredEntry.Username,
  589. PasswordHash: oldCredEntry.PasswordHash,
  590. })
  591. keepUnchange = true
  592. }
  593. }
  594. if !keepUnchange {
  595. //This is a new username with no pw given
  596. utils.SendErrorResponse(w, "Access password for "+credential.Username+" is empty!")
  597. return
  598. }
  599. } else {
  600. //This username have given password
  601. mergedCredentials = append(mergedCredentials, &dynamicproxy.BasicAuthCredentials{
  602. Username: credential.Username,
  603. PasswordHash: auth.Hash(credential.Password),
  604. })
  605. }
  606. }
  607. targetProxy.BasicAuthCredentials = mergedCredentials
  608. //Save it to file
  609. SaveReverseProxyConfig(targetProxy)
  610. //Replace runtime configuration
  611. targetProxy.UpdateToRuntime()
  612. utils.SendOK(w)
  613. } else {
  614. http.Error(w, "invalid usage", http.StatusMethodNotAllowed)
  615. }
  616. }
  617. // List, Update or Remove the exception paths for basic auth.
  618. func ListProxyBasicAuthExceptionPaths(w http.ResponseWriter, r *http.Request) {
  619. if r.Method != http.MethodGet {
  620. http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
  621. }
  622. ep, err := utils.GetPara(r, "ep")
  623. if err != nil {
  624. utils.SendErrorResponse(w, "Invalid ep given")
  625. return
  626. }
  627. //Load the target proxy object from router
  628. targetProxy, err := dynamicProxyRouter.LoadProxy(ep)
  629. if err != nil {
  630. utils.SendErrorResponse(w, err.Error())
  631. return
  632. }
  633. //List all the exception paths for this proxy
  634. results := targetProxy.BasicAuthExceptionRules
  635. if results == nil {
  636. //It is a config from a really old version of zoraxy. Overwrite it with empty array
  637. results = []*dynamicproxy.BasicAuthExceptionRule{}
  638. }
  639. js, _ := json.Marshal(results)
  640. utils.SendJSONResponse(w, string(js))
  641. return
  642. }
  643. func AddProxyBasicAuthExceptionPaths(w http.ResponseWriter, r *http.Request) {
  644. ep, err := utils.PostPara(r, "ep")
  645. if err != nil {
  646. utils.SendErrorResponse(w, "Invalid ep given")
  647. return
  648. }
  649. matchingPrefix, err := utils.PostPara(r, "prefix")
  650. if err != nil {
  651. utils.SendErrorResponse(w, "Invalid matching prefix given")
  652. return
  653. }
  654. //Load the target proxy object from router
  655. targetProxy, err := dynamicProxyRouter.LoadProxy(ep)
  656. if err != nil {
  657. utils.SendErrorResponse(w, err.Error())
  658. return
  659. }
  660. //Check if the prefix starts with /. If not, prepend it
  661. if !strings.HasPrefix(matchingPrefix, "/") {
  662. matchingPrefix = "/" + matchingPrefix
  663. }
  664. //Add a new exception rule if it is not already exists
  665. alreadyExists := false
  666. for _, thisExceptionRule := range targetProxy.BasicAuthExceptionRules {
  667. if thisExceptionRule.PathPrefix == matchingPrefix {
  668. alreadyExists = true
  669. break
  670. }
  671. }
  672. if alreadyExists {
  673. utils.SendErrorResponse(w, "This matching path already exists")
  674. return
  675. }
  676. targetProxy.BasicAuthExceptionRules = append(targetProxy.BasicAuthExceptionRules, &dynamicproxy.BasicAuthExceptionRule{
  677. PathPrefix: strings.TrimSpace(matchingPrefix),
  678. })
  679. //Save configs to runtime and file
  680. targetProxy.UpdateToRuntime()
  681. SaveReverseProxyConfig(targetProxy)
  682. utils.SendOK(w)
  683. }
  684. func RemoveProxyBasicAuthExceptionPaths(w http.ResponseWriter, r *http.Request) {
  685. // Delete a rule
  686. ep, err := utils.PostPara(r, "ep")
  687. if err != nil {
  688. utils.SendErrorResponse(w, "Invalid ep given")
  689. return
  690. }
  691. matchingPrefix, err := utils.PostPara(r, "prefix")
  692. if err != nil {
  693. utils.SendErrorResponse(w, "Invalid matching prefix given")
  694. return
  695. }
  696. // Load the target proxy object from router
  697. targetProxy, err := dynamicProxyRouter.LoadProxy(ep)
  698. if err != nil {
  699. utils.SendErrorResponse(w, err.Error())
  700. return
  701. }
  702. newExceptionRuleList := []*dynamicproxy.BasicAuthExceptionRule{}
  703. matchingExists := false
  704. for _, thisExceptionalRule := range targetProxy.BasicAuthExceptionRules {
  705. if thisExceptionalRule.PathPrefix != matchingPrefix {
  706. newExceptionRuleList = append(newExceptionRuleList, thisExceptionalRule)
  707. } else {
  708. matchingExists = true
  709. }
  710. }
  711. if !matchingExists {
  712. utils.SendErrorResponse(w, "target matching rule not exists")
  713. return
  714. }
  715. targetProxy.BasicAuthExceptionRules = newExceptionRuleList
  716. // Save configs to runtime and file
  717. targetProxy.UpdateToRuntime()
  718. SaveReverseProxyConfig(targetProxy)
  719. utils.SendOK(w)
  720. }
  721. // Report the current status of the reverse proxy server
  722. func ReverseProxyStatus(w http.ResponseWriter, r *http.Request) {
  723. js, _ := json.Marshal(dynamicProxyRouter)
  724. utils.SendJSONResponse(w, string(js))
  725. }
  726. // Toggle a certain rule on and off
  727. func ReverseProxyToggleRuleSet(w http.ResponseWriter, r *http.Request) {
  728. //No need to check for type as root cannot be turned off
  729. ep, err := utils.PostPara(r, "ep")
  730. if err != nil {
  731. utils.SendErrorResponse(w, "invalid ep given")
  732. return
  733. }
  734. targetProxyRule, err := dynamicProxyRouter.LoadProxy(ep)
  735. if err != nil {
  736. utils.SendErrorResponse(w, "invalid endpoint given")
  737. return
  738. }
  739. enableStr, err := utils.PostPara(r, "enable")
  740. if err != nil {
  741. enableStr = "true"
  742. }
  743. //Flip the enable and disabled tag state
  744. ruleDisabled := enableStr == "false"
  745. targetProxyRule.Disabled = ruleDisabled
  746. err = SaveReverseProxyConfig(targetProxyRule)
  747. if err != nil {
  748. utils.SendErrorResponse(w, "unable to save updated rule")
  749. return
  750. }
  751. utils.SendOK(w)
  752. }
  753. func ReverseProxyListDetail(w http.ResponseWriter, r *http.Request) {
  754. eptype, err := utils.PostPara(r, "type") //Support root and host
  755. if err != nil {
  756. utils.SendErrorResponse(w, "type not defined")
  757. return
  758. }
  759. if eptype == "host" {
  760. epname, err := utils.PostPara(r, "epname")
  761. if err != nil {
  762. utils.SendErrorResponse(w, "epname not defined")
  763. return
  764. }
  765. endpointRaw, ok := dynamicProxyRouter.ProxyEndpoints.Load(epname)
  766. if !ok {
  767. utils.SendErrorResponse(w, "proxy rule not found")
  768. return
  769. }
  770. targetEndpoint := dynamicproxy.CopyEndpoint(endpointRaw.(*dynamicproxy.ProxyEndpoint))
  771. js, _ := json.Marshal(targetEndpoint)
  772. utils.SendJSONResponse(w, string(js))
  773. } else if eptype == "root" {
  774. js, _ := json.Marshal(dynamicProxyRouter.Root)
  775. utils.SendJSONResponse(w, string(js))
  776. } else {
  777. utils.SendErrorResponse(w, "Invalid type given")
  778. }
  779. }
  780. func ReverseProxyList(w http.ResponseWriter, r *http.Request) {
  781. eptype, err := utils.PostPara(r, "type") //Support root and host
  782. if err != nil {
  783. utils.SendErrorResponse(w, "type not defined")
  784. return
  785. }
  786. if eptype == "host" {
  787. results := []*dynamicproxy.ProxyEndpoint{}
  788. dynamicProxyRouter.ProxyEndpoints.Range(func(key, value interface{}) bool {
  789. thisEndpoint := dynamicproxy.CopyEndpoint(value.(*dynamicproxy.ProxyEndpoint))
  790. //Clear the auth passwords before showing to front-end
  791. cleanedCredentials := []*dynamicproxy.BasicAuthCredentials{}
  792. for _, user := range thisEndpoint.BasicAuthCredentials {
  793. cleanedCredentials = append(cleanedCredentials, &dynamicproxy.BasicAuthCredentials{
  794. Username: user.Username,
  795. PasswordHash: "",
  796. })
  797. }
  798. thisEndpoint.BasicAuthCredentials = cleanedCredentials
  799. results = append(results, thisEndpoint)
  800. return true
  801. })
  802. sort.Slice(results, func(i, j int) bool {
  803. return results[i].Domain < results[j].Domain
  804. })
  805. js, _ := json.Marshal(results)
  806. utils.SendJSONResponse(w, string(js))
  807. } else if eptype == "root" {
  808. js, _ := json.Marshal(dynamicProxyRouter.Root)
  809. utils.SendJSONResponse(w, string(js))
  810. } else {
  811. utils.SendErrorResponse(w, "Invalid type given")
  812. }
  813. }
  814. // Handle port 80 incoming traffics
  815. func HandleUpdatePort80Listener(w http.ResponseWriter, r *http.Request) {
  816. enabled, err := utils.GetPara(r, "enable")
  817. if err != nil {
  818. //Load the current status
  819. currentEnabled := false
  820. err = sysdb.Read("settings", "listenP80", &currentEnabled)
  821. if err != nil {
  822. utils.SendErrorResponse(w, err.Error())
  823. return
  824. }
  825. js, _ := json.Marshal(currentEnabled)
  826. utils.SendJSONResponse(w, string(js))
  827. } else {
  828. if enabled == "true" {
  829. sysdb.Write("settings", "listenP80", true)
  830. SystemWideLogger.Println("Enabling port 80 listener")
  831. dynamicProxyRouter.UpdatePort80ListenerState(true)
  832. } else if enabled == "false" {
  833. sysdb.Write("settings", "listenP80", false)
  834. SystemWideLogger.Println("Disabling port 80 listener")
  835. dynamicProxyRouter.UpdatePort80ListenerState(false)
  836. } else {
  837. utils.SendErrorResponse(w, "invalid mode given: "+enabled)
  838. }
  839. utils.SendOK(w)
  840. }
  841. }
  842. // Handle https redirect
  843. func HandleUpdateHttpsRedirect(w http.ResponseWriter, r *http.Request) {
  844. useRedirect, err := utils.GetPara(r, "set")
  845. if err != nil {
  846. currentRedirectToHttps := false
  847. //Load the current status
  848. err = sysdb.Read("settings", "redirect", &currentRedirectToHttps)
  849. if err != nil {
  850. utils.SendErrorResponse(w, err.Error())
  851. return
  852. }
  853. js, _ := json.Marshal(currentRedirectToHttps)
  854. utils.SendJSONResponse(w, string(js))
  855. } else {
  856. if dynamicProxyRouter.Option.Port == 80 {
  857. utils.SendErrorResponse(w, "This option is not available when listening on port 80")
  858. return
  859. }
  860. if useRedirect == "true" {
  861. sysdb.Write("settings", "redirect", true)
  862. SystemWideLogger.Println("Updating force HTTPS redirection to true")
  863. dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(true)
  864. } else if useRedirect == "false" {
  865. sysdb.Write("settings", "redirect", false)
  866. SystemWideLogger.Println("Updating force HTTPS redirection to false")
  867. dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(false)
  868. }
  869. utils.SendOK(w)
  870. }
  871. }
  872. // Handle checking if the current user is accessing via the reverse proxied interface
  873. // Of the management interface.
  874. func HandleManagementProxyCheck(w http.ResponseWriter, r *http.Request) {
  875. isProxied := dynamicProxyRouter.IsProxiedSubdomain(r)
  876. js, _ := json.Marshal(isProxied)
  877. utils.SendJSONResponse(w, string(js))
  878. }
  879. func HandleDevelopmentModeChange(w http.ResponseWriter, r *http.Request) {
  880. enableDevelopmentModeStr, err := utils.GetPara(r, "enable")
  881. if err != nil {
  882. //Load the current development mode toggle state
  883. js, _ := json.Marshal(dynamicProxyRouter.Option.NoCache)
  884. utils.SendJSONResponse(w, string(js))
  885. } else {
  886. //Write changes to runtime
  887. enableDevelopmentMode := false
  888. if enableDevelopmentModeStr == "true" {
  889. enableDevelopmentMode = true
  890. }
  891. //Write changes to runtime
  892. dynamicProxyRouter.Option.NoCache = enableDevelopmentMode
  893. //Write changes to database
  894. sysdb.Write("settings", "devMode", enableDevelopmentMode)
  895. utils.SendOK(w)
  896. }
  897. }
  898. // Handle incoming port set. Change the current proxy incoming port
  899. func HandleIncomingPortSet(w http.ResponseWriter, r *http.Request) {
  900. newIncomingPort, err := utils.PostPara(r, "incoming")
  901. if err != nil {
  902. utils.SendErrorResponse(w, "invalid incoming port given")
  903. return
  904. }
  905. newIncomingPortInt, err := strconv.Atoi(newIncomingPort)
  906. if err != nil {
  907. utils.SendErrorResponse(w, "Invalid incoming port given")
  908. return
  909. }
  910. //Check if it is identical as proxy root (recursion!)
  911. if dynamicProxyRouter.Root == nil || dynamicProxyRouter.Root.Domain == "" {
  912. //Check if proxy root is set before checking recursive listen
  913. //Fixing issue #43
  914. utils.SendErrorResponse(w, "Set Proxy Root before changing inbound port")
  915. return
  916. }
  917. proxyRoot := strings.TrimSuffix(dynamicProxyRouter.Root.Domain, "/")
  918. if strings.EqualFold(proxyRoot, "localhost:"+strconv.Itoa(newIncomingPortInt)) || strings.EqualFold(proxyRoot, "127.0.0.1:"+strconv.Itoa(newIncomingPortInt)) {
  919. //Listening port is same as proxy root
  920. //Not allow recursive settings
  921. utils.SendErrorResponse(w, "Recursive listening port! Check your proxy root settings.")
  922. return
  923. }
  924. //Stop and change the setting of the reverse proxy service
  925. if dynamicProxyRouter.Running {
  926. dynamicProxyRouter.StopProxyService()
  927. dynamicProxyRouter.Option.Port = newIncomingPortInt
  928. dynamicProxyRouter.StartProxyService()
  929. } else {
  930. //Only change setting but not starting the proxy service
  931. dynamicProxyRouter.Option.Port = newIncomingPortInt
  932. }
  933. sysdb.Write("settings", "inbound", newIncomingPortInt)
  934. utils.SendOK(w)
  935. }
  936. /* Handle Custom Header Rules */
  937. //List all the custom header defined in this proxy rule
  938. func HandleCustomHeaderList(w http.ResponseWriter, r *http.Request) {
  939. epType, err := utils.PostPara(r, "type")
  940. if err != nil {
  941. utils.SendErrorResponse(w, "endpoint type not defined")
  942. return
  943. }
  944. domain, err := utils.PostPara(r, "domain")
  945. if err != nil {
  946. utils.SendErrorResponse(w, "domain or matching rule not defined")
  947. return
  948. }
  949. var targetProxyEndpoint *dynamicproxy.ProxyEndpoint
  950. if epType == "root" {
  951. targetProxyEndpoint = dynamicProxyRouter.Root
  952. } else {
  953. ep, err := dynamicProxyRouter.LoadProxy(domain)
  954. if err != nil {
  955. utils.SendErrorResponse(w, "target endpoint not exists")
  956. return
  957. }
  958. targetProxyEndpoint = ep
  959. }
  960. //List all custom headers
  961. customHeaderList := targetProxyEndpoint.UserDefinedHeaders
  962. if customHeaderList == nil {
  963. customHeaderList = []*dynamicproxy.UserDefinedHeader{}
  964. }
  965. js, _ := json.Marshal(customHeaderList)
  966. utils.SendJSONResponse(w, string(js))
  967. }
  968. // Add a new header to the target endpoint
  969. func HandleCustomHeaderAdd(w http.ResponseWriter, r *http.Request) {
  970. rewriteType, err := utils.PostPara(r, "type")
  971. if err != nil {
  972. utils.SendErrorResponse(w, "rewriteType not defined")
  973. return
  974. }
  975. domain, err := utils.PostPara(r, "domain")
  976. if err != nil {
  977. utils.SendErrorResponse(w, "domain or matching rule not defined")
  978. return
  979. }
  980. direction, err := utils.PostPara(r, "direction")
  981. if err != nil {
  982. utils.SendErrorResponse(w, "HTTP modifiy direction not set")
  983. return
  984. }
  985. name, err := utils.PostPara(r, "name")
  986. if err != nil {
  987. utils.SendErrorResponse(w, "HTTP header name not set")
  988. return
  989. }
  990. value, err := utils.PostPara(r, "value")
  991. if err != nil && rewriteType == "add" {
  992. utils.SendErrorResponse(w, "HTTP header value not set")
  993. return
  994. }
  995. targetProxyEndpoint, err := dynamicProxyRouter.LoadProxy(domain)
  996. if err != nil {
  997. utils.SendErrorResponse(w, "target endpoint not exists")
  998. return
  999. }
  1000. //Create a Custom Header Defination type
  1001. var rewriteDirection dynamicproxy.HeaderDirection
  1002. if direction == "toOrigin" {
  1003. rewriteDirection = dynamicproxy.HeaderDirection_ZoraxyToUpstream
  1004. } else if direction == "toClient" {
  1005. rewriteDirection = dynamicproxy.HeaderDirection_ZoraxyToDownstream
  1006. } else {
  1007. //Unknown direction
  1008. utils.SendErrorResponse(w, "header rewrite direction not supported")
  1009. return
  1010. }
  1011. isRemove := false
  1012. if rewriteType == "remove" {
  1013. isRemove = true
  1014. }
  1015. headerRewriteDefination := dynamicproxy.UserDefinedHeader{
  1016. Key: name,
  1017. Value: value,
  1018. Direction: rewriteDirection,
  1019. IsRemove: isRemove,
  1020. }
  1021. //Create a new custom header object
  1022. err = targetProxyEndpoint.AddUserDefinedHeader(&headerRewriteDefination)
  1023. if err != nil {
  1024. utils.SendErrorResponse(w, "unable to add header rewrite rule: "+err.Error())
  1025. return
  1026. }
  1027. //Save it (no need reload as header are not handled by dpcore)
  1028. err = SaveReverseProxyConfig(targetProxyEndpoint)
  1029. if err != nil {
  1030. utils.SendErrorResponse(w, "unable to save update")
  1031. return
  1032. }
  1033. utils.SendOK(w)
  1034. }
  1035. // Remove a header from the target endpoint
  1036. func HandleCustomHeaderRemove(w http.ResponseWriter, r *http.Request) {
  1037. domain, err := utils.PostPara(r, "domain")
  1038. if err != nil {
  1039. utils.SendErrorResponse(w, "domain or matching rule not defined")
  1040. return
  1041. }
  1042. name, err := utils.PostPara(r, "name")
  1043. if err != nil {
  1044. utils.SendErrorResponse(w, "HTTP header name not set")
  1045. return
  1046. }
  1047. targetProxyEndpoint, err := dynamicProxyRouter.LoadProxy(domain)
  1048. if err != nil {
  1049. utils.SendErrorResponse(w, "target endpoint not exists")
  1050. return
  1051. }
  1052. err = targetProxyEndpoint.RemoveUserDefinedHeader(name)
  1053. if err != nil {
  1054. utils.SendErrorResponse(w, "unable to remove header rewrite rule: "+err.Error())
  1055. return
  1056. }
  1057. err = SaveReverseProxyConfig(targetProxyEndpoint)
  1058. if err != nil {
  1059. utils.SendErrorResponse(w, "unable to save update")
  1060. return
  1061. }
  1062. utils.SendOK(w)
  1063. }
  1064. // Handle view or edit HSTS states
  1065. func HandleHSTSState(w http.ResponseWriter, r *http.Request) {
  1066. domain, err := utils.PostPara(r, "domain")
  1067. if err != nil {
  1068. domain, err = utils.GetPara(r, "domain")
  1069. if err != nil {
  1070. utils.SendErrorResponse(w, "domain or matching rule not defined")
  1071. return
  1072. }
  1073. }
  1074. targetProxyEndpoint, err := dynamicProxyRouter.LoadProxy(domain)
  1075. if err != nil {
  1076. utils.SendErrorResponse(w, "target endpoint not exists")
  1077. return
  1078. }
  1079. if r.Method == http.MethodGet {
  1080. //Return current HSTS enable state
  1081. hstsAge := targetProxyEndpoint.HSTSMaxAge
  1082. js, _ := json.Marshal(hstsAge)
  1083. utils.SendJSONResponse(w, string(js))
  1084. return
  1085. } else if r.Method == http.MethodPost {
  1086. newMaxAge, err := utils.PostInt(r, "maxage")
  1087. if err != nil {
  1088. utils.SendErrorResponse(w, "maxage not defeined")
  1089. return
  1090. }
  1091. if newMaxAge == 0 || newMaxAge >= 31536000 {
  1092. targetProxyEndpoint.HSTSMaxAge = int64(newMaxAge)
  1093. SaveReverseProxyConfig(targetProxyEndpoint)
  1094. targetProxyEndpoint.UpdateToRuntime()
  1095. } else {
  1096. utils.SendErrorResponse(w, "invalid max age given")
  1097. return
  1098. }
  1099. utils.SendOK(w)
  1100. return
  1101. }
  1102. http.Error(w, "405 - Method not allowed", http.StatusMethodNotAllowed)
  1103. }
  1104. // HandlePermissionPolicy handle read or write to permission policy
  1105. func HandlePermissionPolicy(w http.ResponseWriter, r *http.Request) {
  1106. domain, err := utils.PostPara(r, "domain")
  1107. if err != nil {
  1108. domain, err = utils.GetPara(r, "domain")
  1109. if err != nil {
  1110. utils.SendErrorResponse(w, "domain or matching rule not defined")
  1111. return
  1112. }
  1113. }
  1114. targetProxyEndpoint, err := dynamicProxyRouter.LoadProxy(domain)
  1115. if err != nil {
  1116. utils.SendErrorResponse(w, "target endpoint not exists")
  1117. return
  1118. }
  1119. if r.Method == http.MethodGet {
  1120. type CurrentPolicyState struct {
  1121. PPEnabled bool
  1122. CurrentPolicy *permissionpolicy.PermissionsPolicy
  1123. }
  1124. currentPolicy := permissionpolicy.GetDefaultPermissionPolicy()
  1125. if targetProxyEndpoint.PermissionPolicy != nil {
  1126. currentPolicy = targetProxyEndpoint.PermissionPolicy
  1127. }
  1128. result := CurrentPolicyState{
  1129. PPEnabled: targetProxyEndpoint.EnablePermissionPolicyHeader,
  1130. CurrentPolicy: currentPolicy,
  1131. }
  1132. js, _ := json.Marshal(result)
  1133. utils.SendJSONResponse(w, string(js))
  1134. return
  1135. } else if r.Method == http.MethodPost {
  1136. }
  1137. http.Error(w, "405 - Method not allowed", http.StatusMethodNotAllowed)
  1138. }