reverseproxy.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. package main
  2. import (
  3. "encoding/json"
  4. "log"
  5. "net/http"
  6. "path/filepath"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "imuslab.com/arozos/ReverseProxy/mod/dynamicproxy"
  11. "imuslab.com/arozos/ReverseProxy/mod/utils"
  12. )
  13. var (
  14. dynamicProxyRouter *dynamicproxy.Router
  15. )
  16. // Add user customizable reverse proxy
  17. func ReverseProxtInit() {
  18. inboundPort := 80
  19. if sysdb.KeyExists("settings", "inbound") {
  20. sysdb.Read("settings", "inbound", &inboundPort)
  21. log.Println("Serving inbound port ", inboundPort)
  22. } else {
  23. log.Println("Inbound port not set. Using default (80)")
  24. }
  25. useTls := false
  26. sysdb.Read("settings", "usetls", &useTls)
  27. if useTls {
  28. log.Println("TLS mode enabled. Serving proxxy request with TLS")
  29. } else {
  30. log.Println("TLS mode disabled. Serving proxy request with plain http")
  31. }
  32. forceHttpsRedirect := false
  33. sysdb.Read("settings", "redirect", &forceHttpsRedirect)
  34. if forceHttpsRedirect {
  35. log.Println("Force HTTPS mode enabled")
  36. } else {
  37. log.Println("Force HTTPS mode disabled")
  38. }
  39. dprouter, err := dynamicproxy.NewDynamicProxy(dynamicproxy.RouterOption{
  40. Port: inboundPort,
  41. UseTls: useTls,
  42. ForceHttpsRedirect: forceHttpsRedirect,
  43. TlsManager: tlsCertManager,
  44. RedirectRuleTable: redirectTable,
  45. })
  46. if err != nil {
  47. log.Println(err.Error())
  48. return
  49. }
  50. dynamicProxyRouter = dprouter
  51. //Load all conf from files
  52. confs, _ := filepath.Glob("./conf/*.config")
  53. for _, conf := range confs {
  54. record, err := LoadReverseProxyConfig(conf)
  55. if err != nil {
  56. log.Println("Failed to load "+filepath.Base(conf), err.Error())
  57. return
  58. }
  59. if record.ProxyType == "root" {
  60. dynamicProxyRouter.SetRootProxy(record.ProxyTarget, record.UseTLS)
  61. } else if record.ProxyType == "subd" {
  62. dynamicProxyRouter.AddSubdomainRoutingService(record.Rootname, record.ProxyTarget, record.UseTLS)
  63. } else if record.ProxyType == "vdir" {
  64. dynamicProxyRouter.AddVirtualDirectoryProxyService(record.Rootname, record.ProxyTarget, record.UseTLS)
  65. } else {
  66. log.Println("Unsupported endpoint type: " + record.ProxyType + ". Skipping " + filepath.Base(conf))
  67. }
  68. }
  69. /*
  70. dynamicProxyRouter.SetRootProxy("192.168.0.107:8080", false)
  71. dynamicProxyRouter.AddSubdomainRoutingService("aroz.localhost", "192.168.0.107:8080/private/AOB/", false)
  72. dynamicProxyRouter.AddSubdomainRoutingService("loopback.localhost", "localhost:8080", false)
  73. dynamicProxyRouter.AddSubdomainRoutingService("git.localhost", "mc.alanyeung.co:3000", false)
  74. dynamicProxyRouter.AddVirtualDirectoryProxyService("/git/server/", "mc.alanyeung.co:3000", false)
  75. */
  76. //Start Service
  77. //Not sure why but delay must be added if you have another
  78. //reverse proxy server in front of this service
  79. time.Sleep(300 * time.Millisecond)
  80. dynamicProxyRouter.StartProxyService()
  81. log.Println("Dynamic Reverse Proxy service started")
  82. }
  83. func ReverseProxyHandleOnOff(w http.ResponseWriter, r *http.Request) {
  84. enable, _ := utils.PostPara(r, "enable") //Support root, vdir and subd
  85. if enable == "true" {
  86. err := dynamicProxyRouter.StartProxyService()
  87. if err != nil {
  88. utils.SendErrorResponse(w, err.Error())
  89. return
  90. }
  91. } else {
  92. err := dynamicProxyRouter.StopProxyService()
  93. if err != nil {
  94. utils.SendErrorResponse(w, err.Error())
  95. return
  96. }
  97. }
  98. utils.SendOK(w)
  99. }
  100. func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
  101. eptype, err := utils.PostPara(r, "type") //Support root, vdir and subd
  102. if err != nil {
  103. utils.SendErrorResponse(w, "type not defined")
  104. return
  105. }
  106. endpoint, err := utils.PostPara(r, "ep")
  107. if err != nil {
  108. utils.SendErrorResponse(w, "endpoint not defined")
  109. return
  110. }
  111. tls, _ := utils.PostPara(r, "tls")
  112. if tls == "" {
  113. tls = "false"
  114. }
  115. useTLS := (tls == "true")
  116. rootname := ""
  117. if eptype == "vdir" {
  118. vdir, err := utils.PostPara(r, "rootname")
  119. if err != nil {
  120. utils.SendErrorResponse(w, "vdir not defined")
  121. return
  122. }
  123. if !strings.HasPrefix(vdir, "/") {
  124. vdir = "/" + vdir
  125. }
  126. rootname = vdir
  127. dynamicProxyRouter.AddVirtualDirectoryProxyService(vdir, endpoint, useTLS)
  128. } else if eptype == "subd" {
  129. subdomain, err := utils.PostPara(r, "rootname")
  130. if err != nil {
  131. utils.SendErrorResponse(w, "subdomain not defined")
  132. return
  133. }
  134. rootname = subdomain
  135. dynamicProxyRouter.AddSubdomainRoutingService(subdomain, endpoint, useTLS)
  136. } else if eptype == "root" {
  137. rootname = "root"
  138. dynamicProxyRouter.SetRootProxy(endpoint, useTLS)
  139. } else {
  140. //Invalid eptype
  141. utils.SendErrorResponse(w, "Invalid endpoint type")
  142. return
  143. }
  144. //Save it
  145. SaveReverseProxyConfig(eptype, rootname, endpoint, useTLS)
  146. utils.SendOK(w)
  147. }
  148. func DeleteProxyEndpoint(w http.ResponseWriter, r *http.Request) {
  149. ep, err := utils.GetPara(r, "ep")
  150. if err != nil {
  151. utils.SendErrorResponse(w, "Invalid ep given")
  152. }
  153. ptype, err := utils.PostPara(r, "ptype")
  154. if err != nil {
  155. utils.SendErrorResponse(w, "Invalid ptype given")
  156. }
  157. err = dynamicProxyRouter.RemoveProxy(ptype, ep)
  158. if err != nil {
  159. utils.SendErrorResponse(w, err.Error())
  160. }
  161. RemoveReverseProxyConfig(ep)
  162. utils.SendOK(w)
  163. }
  164. func ReverseProxyStatus(w http.ResponseWriter, r *http.Request) {
  165. js, _ := json.Marshal(dynamicProxyRouter)
  166. utils.SendJSONResponse(w, string(js))
  167. }
  168. func ReverseProxyList(w http.ResponseWriter, r *http.Request) {
  169. eptype, err := utils.PostPara(r, "type") //Support root, vdir and subd
  170. if err != nil {
  171. utils.SendErrorResponse(w, "type not defined")
  172. return
  173. }
  174. if eptype == "vdir" {
  175. results := []*dynamicproxy.ProxyEndpoint{}
  176. dynamicProxyRouter.ProxyEndpoints.Range(func(key, value interface{}) bool {
  177. results = append(results, value.(*dynamicproxy.ProxyEndpoint))
  178. return true
  179. })
  180. js, _ := json.Marshal(results)
  181. utils.SendJSONResponse(w, string(js))
  182. } else if eptype == "subd" {
  183. results := []*dynamicproxy.SubdomainEndpoint{}
  184. dynamicProxyRouter.SubdomainEndpoint.Range(func(key, value interface{}) bool {
  185. results = append(results, value.(*dynamicproxy.SubdomainEndpoint))
  186. return true
  187. })
  188. js, _ := json.Marshal(results)
  189. utils.SendJSONResponse(w, string(js))
  190. } else if eptype == "root" {
  191. js, _ := json.Marshal(dynamicProxyRouter.Root)
  192. utils.SendJSONResponse(w, string(js))
  193. } else {
  194. utils.SendErrorResponse(w, "Invalid type given")
  195. }
  196. }
  197. // Handle https redirect
  198. func HandleUpdateHttpsRedirect(w http.ResponseWriter, r *http.Request) {
  199. useRedirect, err := utils.GetPara(r, "set")
  200. if err != nil {
  201. currentRedirectToHttps := false
  202. //Load the current status
  203. err = sysdb.Read("settings", "redirect", &currentRedirectToHttps)
  204. if err != nil {
  205. utils.SendErrorResponse(w, err.Error())
  206. return
  207. }
  208. js, _ := json.Marshal(currentRedirectToHttps)
  209. utils.SendJSONResponse(w, string(js))
  210. } else {
  211. if useRedirect == "true" {
  212. sysdb.Write("settings", "redirect", true)
  213. log.Println("Updating force HTTPS redirection to true")
  214. dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(true)
  215. } else if useRedirect == "false" {
  216. sysdb.Write("settings", "redirect", false)
  217. log.Println("Updating force HTTPS redirection to false")
  218. dynamicProxyRouter.UpdateHttpToHttpsRedirectSetting(false)
  219. }
  220. utils.SendOK(w)
  221. }
  222. }
  223. // Handle incoming port set. Change the current proxy incoming port
  224. func HandleIncomingPortSet(w http.ResponseWriter, r *http.Request) {
  225. newIncomingPort, err := utils.PostPara(r, "incoming")
  226. if err != nil {
  227. utils.SendErrorResponse(w, "invalid incoming port given")
  228. return
  229. }
  230. newIncomingPortInt, err := strconv.Atoi(newIncomingPort)
  231. if err != nil {
  232. utils.SendErrorResponse(w, "invalid incoming port given")
  233. return
  234. }
  235. //Stop and change the setting of the reverse proxy service
  236. if dynamicProxyRouter.Running {
  237. dynamicProxyRouter.StopProxyService()
  238. dynamicProxyRouter.ListenPort = newIncomingPortInt
  239. dynamicProxyRouter.StartProxyService()
  240. } else {
  241. //Only change setting but not starting the proxy service
  242. dynamicProxyRouter.ListenPort = newIncomingPortInt
  243. }
  244. sysdb.Write("settings", "inbound", newIncomingPortInt)
  245. utils.SendOK(w)
  246. }