1
0

reverseproxy.go 39 KB

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