reverseproxy.go 40 KB

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