accesslist.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. package main
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "strings"
  6. "github.com/google/uuid"
  7. "github.com/microcosm-cc/bluemonday"
  8. "imuslab.com/zoraxy/mod/access"
  9. "imuslab.com/zoraxy/mod/utils"
  10. )
  11. /*
  12. accesslist.go
  13. This script file is added to extend the
  14. reverse proxy function to include
  15. banning / whitelist a specific IP address or country code
  16. */
  17. /*
  18. General Function
  19. */
  20. func handleListAccessRules(w http.ResponseWriter, r *http.Request) {
  21. allAccessRules := accessController.ListAllAccessRules()
  22. js, _ := json.Marshal(allAccessRules)
  23. utils.SendJSONResponse(w, string(js))
  24. }
  25. // Create a new access rule, require name and desc only
  26. func handleCreateAccessRule(w http.ResponseWriter, r *http.Request) {
  27. ruleName, err := utils.PostPara(r, "name")
  28. if err != nil {
  29. utils.SendErrorResponse(w, "invalid rule name")
  30. return
  31. }
  32. ruleDesc, _ := utils.PostPara(r, "desc")
  33. //Filter out injection if any
  34. p := bluemonday.StripTagsPolicy()
  35. ruleName = p.Sanitize(ruleName)
  36. ruleDesc = p.Sanitize(ruleDesc)
  37. ruleUUID := uuid.New().String()
  38. newAccessRule := access.AccessRule{
  39. ID: ruleUUID,
  40. Name: ruleName,
  41. Desc: ruleDesc,
  42. BlacklistEnabled: false,
  43. WhitelistEnabled: false,
  44. }
  45. //Add it to runtime
  46. err = accessController.AddNewAccessRule(&newAccessRule)
  47. if err != nil {
  48. utils.SendErrorResponse(w, err.Error())
  49. return
  50. }
  51. utils.SendOK(w)
  52. }
  53. // Handle removing an access rule. All proxy endpoint using this rule will be
  54. // set to use the default rule
  55. func handleRemoveAccessRule(w http.ResponseWriter, r *http.Request) {
  56. ruleID, err := utils.PostPara(r, "id")
  57. if err != nil {
  58. utils.SendErrorResponse(w, "invalid rule id given")
  59. return
  60. }
  61. if ruleID == "default" {
  62. utils.SendErrorResponse(w, "default access rule cannot be removed")
  63. return
  64. }
  65. ruleID = strings.TrimSpace(ruleID)
  66. //Set all proxy hosts that use this access rule back to using "default"
  67. allProxyEndpoints := dynamicProxyRouter.GetProxyEndpointsAsMap()
  68. for _, proxyEndpoint := range allProxyEndpoints {
  69. if strings.EqualFold(proxyEndpoint.AccessFilterUUID, ruleID) {
  70. //This proxy endpoint is using the current access filter.
  71. //set it to default
  72. proxyEndpoint.AccessFilterUUID = "default"
  73. proxyEndpoint.UpdateToRuntime()
  74. err = SaveReverseProxyConfig(proxyEndpoint)
  75. if err != nil {
  76. SystemWideLogger.PrintAndLog("Access", "Unable to save updated proxy endpoint "+proxyEndpoint.RootOrMatchingDomain, err)
  77. } else {
  78. SystemWideLogger.PrintAndLog("Access", "Updated "+proxyEndpoint.RootOrMatchingDomain+" access filter to \"default\"", nil)
  79. }
  80. }
  81. }
  82. //Remove the access rule by ID
  83. err = accessController.RemoveAccessRuleByID(ruleID)
  84. if err != nil {
  85. utils.SendErrorResponse(w, err.Error())
  86. return
  87. }
  88. SystemWideLogger.PrintAndLog("Access", "Access Rule "+ruleID+" removed", nil)
  89. utils.SendOK(w)
  90. }
  91. // Only the name and desc, for other properties use blacklist / whitelist api
  92. func handleUpadateAccessRule(w http.ResponseWriter, r *http.Request) {
  93. ruleID, err := utils.PostPara(r, "id")
  94. if err != nil {
  95. utils.SendErrorResponse(w, "invalid rule id")
  96. return
  97. }
  98. ruleName, err := utils.PostPara(r, "name")
  99. if err != nil {
  100. utils.SendErrorResponse(w, "invalid rule name")
  101. return
  102. }
  103. ruleDesc, _ := utils.PostPara(r, "desc")
  104. //Filter anything weird
  105. p := bluemonday.StrictPolicy()
  106. ruleName = p.Sanitize(ruleName)
  107. ruleDesc = p.Sanitize(ruleDesc)
  108. err = accessController.UpdateAccessRule(ruleID, ruleName, ruleDesc)
  109. if err != nil {
  110. utils.SendErrorResponse(w, err.Error())
  111. return
  112. }
  113. utils.SendOK(w)
  114. }
  115. /*
  116. Blacklist Related
  117. */
  118. // List a of blacklisted ip address or country code
  119. func handleListBlacklisted(w http.ResponseWriter, r *http.Request) {
  120. bltype, err := utils.GetPara(r, "type")
  121. if err != nil {
  122. bltype = "country"
  123. }
  124. ruleID, err := utils.GetPara(r, "id")
  125. if err != nil {
  126. //Use default if not set
  127. ruleID = "default"
  128. }
  129. //Load the target rule from access controller
  130. rule, err := accessController.GetAccessRuleByID(ruleID)
  131. if err != nil {
  132. utils.SendErrorResponse(w, err.Error())
  133. return
  134. }
  135. resulst := []string{}
  136. if bltype == "country" {
  137. resulst = rule.GetAllBlacklistedCountryCode()
  138. } else if bltype == "ip" {
  139. resulst = rule.GetAllBlacklistedIp()
  140. }
  141. js, _ := json.Marshal(resulst)
  142. utils.SendJSONResponse(w, string(js))
  143. }
  144. func handleCountryBlacklistAdd(w http.ResponseWriter, r *http.Request) {
  145. countryCode, err := utils.PostPara(r, "cc")
  146. if err != nil {
  147. utils.SendErrorResponse(w, "invalid or empty country code")
  148. return
  149. }
  150. ruleID, err := utils.GetPara(r, "id")
  151. if err != nil {
  152. ruleID = "default"
  153. }
  154. comment, _ := utils.GetPara(r, "comment")
  155. p := bluemonday.StripTagsPolicy()
  156. comment = p.Sanitize(comment)
  157. //Load the target rule from access controller
  158. rule, err := accessController.GetAccessRuleByID(ruleID)
  159. if err != nil {
  160. utils.SendErrorResponse(w, err.Error())
  161. return
  162. }
  163. rule.AddCountryCodeToBlackList(countryCode, comment)
  164. utils.SendOK(w)
  165. }
  166. func handleCountryBlacklistRemove(w http.ResponseWriter, r *http.Request) {
  167. countryCode, err := utils.PostPara(r, "cc")
  168. if err != nil {
  169. utils.SendErrorResponse(w, "invalid or empty country code")
  170. return
  171. }
  172. ruleID, err := utils.GetPara(r, "id")
  173. if err != nil {
  174. ruleID = "default"
  175. }
  176. //Load the target rule from access controller
  177. rule, err := accessController.GetAccessRuleByID(ruleID)
  178. if err != nil {
  179. utils.SendErrorResponse(w, err.Error())
  180. return
  181. }
  182. rule.RemoveCountryCodeFromBlackList(countryCode)
  183. utils.SendOK(w)
  184. }
  185. func handleIpBlacklistAdd(w http.ResponseWriter, r *http.Request) {
  186. ipAddr, err := utils.PostPara(r, "ip")
  187. if err != nil {
  188. utils.SendErrorResponse(w, "invalid or empty ip address")
  189. return
  190. }
  191. ruleID, err := utils.GetPara(r, "id")
  192. if err != nil {
  193. ruleID = "default"
  194. }
  195. //Load the target rule from access controller
  196. rule, err := accessController.GetAccessRuleByID(ruleID)
  197. if err != nil {
  198. utils.SendErrorResponse(w, err.Error())
  199. return
  200. }
  201. comment, _ := utils.GetPara(r, "comment")
  202. p := bluemonday.StripTagsPolicy()
  203. comment = p.Sanitize(comment)
  204. rule.AddIPToBlackList(ipAddr, comment)
  205. utils.SendOK(w)
  206. }
  207. func handleIpBlacklistRemove(w http.ResponseWriter, r *http.Request) {
  208. ipAddr, err := utils.PostPara(r, "ip")
  209. if err != nil {
  210. utils.SendErrorResponse(w, "invalid or empty ip address")
  211. return
  212. }
  213. ruleID, err := utils.GetPara(r, "id")
  214. if err != nil {
  215. ruleID = "default"
  216. }
  217. //Load the target rule from access controller
  218. rule, err := accessController.GetAccessRuleByID(ruleID)
  219. if err != nil {
  220. utils.SendErrorResponse(w, err.Error())
  221. return
  222. }
  223. rule.RemoveIPFromBlackList(ipAddr)
  224. utils.SendOK(w)
  225. }
  226. func handleBlacklistEnable(w http.ResponseWriter, r *http.Request) {
  227. enable, _ := utils.PostPara(r, "enable")
  228. ruleID, err := utils.GetPara(r, "id")
  229. if err != nil {
  230. ruleID = "default"
  231. }
  232. rule, err := accessController.GetAccessRuleByID(ruleID)
  233. if err != nil {
  234. utils.SendErrorResponse(w, err.Error())
  235. return
  236. }
  237. if enable == "" {
  238. //enable paramter not set
  239. currentEnabled := rule.BlacklistEnabled
  240. js, _ := json.Marshal(currentEnabled)
  241. utils.SendJSONResponse(w, string(js))
  242. } else {
  243. if enable == "true" {
  244. rule.ToggleBlacklist(true)
  245. } else if enable == "false" {
  246. rule.ToggleBlacklist(false)
  247. } else {
  248. utils.SendErrorResponse(w, "invalid enable state: only true and false is accepted")
  249. return
  250. }
  251. utils.SendOK(w)
  252. }
  253. }
  254. /*
  255. Whitelist Related
  256. */
  257. func handleListWhitelisted(w http.ResponseWriter, r *http.Request) {
  258. bltype, err := utils.GetPara(r, "type")
  259. if err != nil {
  260. bltype = "country"
  261. }
  262. ruleID, err := utils.GetPara(r, "id")
  263. if err != nil {
  264. ruleID = "default"
  265. }
  266. rule, err := accessController.GetAccessRuleByID(ruleID)
  267. if err != nil {
  268. utils.SendErrorResponse(w, err.Error())
  269. return
  270. }
  271. resulst := []*access.WhitelistEntry{}
  272. if bltype == "country" {
  273. resulst = rule.GetAllWhitelistedCountryCode()
  274. } else if bltype == "ip" {
  275. resulst = rule.GetAllWhitelistedIp()
  276. }
  277. js, _ := json.Marshal(resulst)
  278. utils.SendJSONResponse(w, string(js))
  279. }
  280. func handleCountryWhitelistAdd(w http.ResponseWriter, r *http.Request) {
  281. countryCode, err := utils.PostPara(r, "cc")
  282. if err != nil {
  283. utils.SendErrorResponse(w, "invalid or empty country code")
  284. return
  285. }
  286. ruleID, err := utils.GetPara(r, "id")
  287. if err != nil {
  288. ruleID = "default"
  289. }
  290. rule, err := accessController.GetAccessRuleByID(ruleID)
  291. if err != nil {
  292. utils.SendErrorResponse(w, err.Error())
  293. return
  294. }
  295. comment, _ := utils.PostPara(r, "comment")
  296. p := bluemonday.StrictPolicy()
  297. comment = p.Sanitize(comment)
  298. rule.AddCountryCodeToWhitelist(countryCode, comment)
  299. utils.SendOK(w)
  300. }
  301. func handleCountryWhitelistRemove(w http.ResponseWriter, r *http.Request) {
  302. countryCode, err := utils.PostPara(r, "cc")
  303. if err != nil {
  304. utils.SendErrorResponse(w, "invalid or empty country code")
  305. return
  306. }
  307. ruleID, err := utils.GetPara(r, "id")
  308. if err != nil {
  309. ruleID = "default"
  310. }
  311. rule, err := accessController.GetAccessRuleByID(ruleID)
  312. if err != nil {
  313. utils.SendErrorResponse(w, err.Error())
  314. return
  315. }
  316. rule.RemoveCountryCodeFromWhitelist(countryCode)
  317. utils.SendOK(w)
  318. }
  319. func handleIpWhitelistAdd(w http.ResponseWriter, r *http.Request) {
  320. ipAddr, err := utils.PostPara(r, "ip")
  321. if err != nil {
  322. utils.SendErrorResponse(w, "invalid or empty ip address")
  323. return
  324. }
  325. ruleID, err := utils.GetPara(r, "id")
  326. if err != nil {
  327. ruleID = "default"
  328. }
  329. rule, err := accessController.GetAccessRuleByID(ruleID)
  330. if err != nil {
  331. utils.SendErrorResponse(w, err.Error())
  332. return
  333. }
  334. comment, _ := utils.PostPara(r, "comment")
  335. p := bluemonday.StrictPolicy()
  336. comment = p.Sanitize(comment)
  337. rule.AddIPToWhiteList(ipAddr, comment)
  338. utils.SendOK(w)
  339. }
  340. func handleIpWhitelistRemove(w http.ResponseWriter, r *http.Request) {
  341. ipAddr, err := utils.PostPara(r, "ip")
  342. if err != nil {
  343. utils.SendErrorResponse(w, "invalid or empty ip address")
  344. return
  345. }
  346. ruleID, err := utils.GetPara(r, "id")
  347. if err != nil {
  348. ruleID = "default"
  349. }
  350. rule, err := accessController.GetAccessRuleByID(ruleID)
  351. if err != nil {
  352. utils.SendErrorResponse(w, err.Error())
  353. return
  354. }
  355. rule.RemoveIPFromWhiteList(ipAddr)
  356. utils.SendOK(w)
  357. }
  358. func handleWhitelistEnable(w http.ResponseWriter, r *http.Request) {
  359. enable, _ := utils.PostPara(r, "enable")
  360. ruleID, err := utils.GetPara(r, "id")
  361. if err != nil {
  362. ruleID = "default"
  363. }
  364. rule, err := accessController.GetAccessRuleByID(ruleID)
  365. if err != nil {
  366. utils.SendErrorResponse(w, err.Error())
  367. return
  368. }
  369. if enable == "" {
  370. //Return the current enabled state
  371. currentEnabled := rule.WhitelistEnabled
  372. js, _ := json.Marshal(currentEnabled)
  373. utils.SendJSONResponse(w, string(js))
  374. } else {
  375. if enable == "true" {
  376. rule.ToggleWhitelist(true)
  377. } else if enable == "false" {
  378. rule.ToggleWhitelist(false)
  379. } else {
  380. utils.SendErrorResponse(w, "invalid enable state: only true and false is accepted")
  381. return
  382. }
  383. utils.SendOK(w)
  384. }
  385. }