reverseproxy.go 39 KB

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