reverseproxy.go 40 KB

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