shadowsocks-libev.lua 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. -- Copyright 2017 Yousong Zhou <yszhou4tech@gmail.com>
  2. -- Licensed to the public under the Apache License 2.0.
  3. local _up = getfenv(3)
  4. local ut = require("luci.util")
  5. local sys = require("luci.sys")
  6. local ds = require("luci.dispatcher")
  7. local nw = require("luci.model.network")
  8. nw.init()
  9. module("luci.model.shadowsocks-libev", function(m)
  10. setmetatable(m, {__index=function (self, k)
  11. local tb = _up
  12. return rawget(self, k) or _up[k]
  13. end})
  14. end)
  15. function values_actions(o)
  16. o:value("bypass")
  17. o:value("forward")
  18. if o.option ~= "dst_default" then
  19. o:value("checkdst")
  20. end
  21. end
  22. function values_redir(o, xmode)
  23. o.map.uci.foreach("shadowsocks-libev", "ss_redir", function(sdata)
  24. local disabled = ucival_to_bool(sdata["disabled"])
  25. local sname = sdata[".name"]
  26. local mode = sdata["mode"] or "tcp_only"
  27. if not disabled and mode:find(xmode) then
  28. local desc = "%s - %s" % {sname, mode}
  29. o:value(sname, desc)
  30. end
  31. end)
  32. o:value("", "<unset>")
  33. o.default = ""
  34. end
  35. function values_serverlist(o)
  36. o.map.uci.foreach("shadowsocks-libev", "server", function(sdata)
  37. local sname = sdata[".name"]
  38. local server = sdata["server"]
  39. local server_port = sdata["server_port"]
  40. if server and server_port then
  41. local desc = "%s - %s:%s" % {sname, sdata["server"], sdata["server_port"]}
  42. o:value(sname, desc)
  43. end
  44. end)
  45. end
  46. function values_ipaddr(o)
  47. for _, v in ipairs(nw:get_interfaces()) do
  48. for _, a in ipairs(v:ipaddrs()) do
  49. o:value(a:host():string(), '%s (%s)' %{ a:host(), v:shortname() })
  50. end
  51. end
  52. end
  53. function values_ifnames(o)
  54. for _, v in ipairs(sys.net.devices()) do
  55. o:value(v)
  56. end
  57. end
  58. function options_client(s, tab)
  59. local o
  60. o = s:taboption(tab, ListValue, "server", translate("Remote server"))
  61. values_serverlist(o)
  62. o = s:taboption(tab, Value, "local_address", translate("Local address"))
  63. o.datatype = "ipaddr"
  64. o.placeholder = "0.0.0.0"
  65. values_ipaddr(o)
  66. o = s:taboption(tab, Value, "local_port", translate("Local port"))
  67. o.datatype = "port"
  68. end
  69. function options_server(s, tab)
  70. local o
  71. local optfunc
  72. if tab == nil then
  73. optfunc = function(...) return s:option(...) end
  74. else
  75. optfunc = function(...) return s:taboption(tab, ...) end
  76. end
  77. o = optfunc(Value, "server", translate("Server"))
  78. o.datatype = "host"
  79. o.size = 16
  80. o = optfunc(Value, "server_port", translate("Server port"))
  81. o.datatype = "port"
  82. o.size = 5
  83. o = optfunc(ListValue, "method", translate("Method"))
  84. for _, m in ipairs(methods) do
  85. o:value(m)
  86. end
  87. o = optfunc(Value, "key", translate("Key (base64 encoding)"))
  88. o.datatype = "base64"
  89. o.password = true
  90. o.size = 12
  91. o = optfunc(Value, "password", translate("Password"))
  92. o.password = true
  93. o.size = 12
  94. end
  95. function options_common(s, tab)
  96. local o
  97. o = s:taboption(tab, ListValue, "mode", translate("Mode of operation"))
  98. for _, m in ipairs(modes) do
  99. o:value(m)
  100. end
  101. o.default = "tcp_and_udp"
  102. o = s:taboption(tab, Value, "mtu", translate("MTU"))
  103. o.datatype = "uinteger"
  104. o = s:taboption(tab, Value, "timeout", translate("Timeout (sec)"))
  105. o.datatype = "uinteger"
  106. s:taboption(tab, Value, "user", translate("Run as"))
  107. s:taboption(tab, Flag, "verbose", translate("Verbose"))
  108. s:taboption(tab, Flag, "ipv6_first", translate("IPv6 First"), translate("Prefer IPv6 addresses when resolving names"))
  109. s:taboption(tab, Flag, "fast_open", translate("Enable TCP Fast Open"))
  110. s:taboption(tab, Flag, "reuse_port", translate("Enable SO_REUSEPORT"))
  111. end
  112. function ucival_to_bool(val)
  113. return val == "true" or val == "1" or val == "yes" or val == "on"
  114. end
  115. function cfgvalue_overview(sdata)
  116. local stype = sdata[".type"]
  117. local lines = {}
  118. if stype == "ss_server" then
  119. cfgvalue_overview_(sdata, lines, names_options_server)
  120. cfgvalue_overview_(sdata, lines, names_options_common)
  121. cfgvalue_overview_(sdata, lines, {
  122. "bind_address",
  123. "manager_address",
  124. })
  125. elseif stype == "ss_local" or stype == "ss_redir" or stype == "ss_tunnel" then
  126. cfgvalue_overview_(sdata, lines, names_options_client)
  127. if stype == "ss_tunnel" then
  128. cfgvalue_overview_(sdata, lines, {"tunnel_address"})
  129. elseif stype == "ss_redir" then
  130. cfgvalue_overview_(sdata, lines, {"disable_sni"})
  131. end
  132. cfgvalue_overview_(sdata, lines, names_options_common)
  133. else
  134. return nil, nil
  135. end
  136. local sname = sdata[".name"]
  137. local key = "%s.%s" % {stype, sname}
  138. local value = {
  139. [".name"] = sname,
  140. name = '%s.<var>%s</var>' % {stype, sname},
  141. overview = table.concat(lines, "</br>"),
  142. disabled = ucival_to_bool(sdata["disabled"]),
  143. }
  144. return key, value
  145. end
  146. function cfgvalue_overview_(sdata, lines, names)
  147. local line
  148. for _, n in ipairs(names) do
  149. local v = sdata[n]
  150. if v ~= nil then
  151. if n == "key" or n == "password" then
  152. v = translate("<hidden>")
  153. end
  154. local fv = "<var>%s</var>" % ut.pcdata(v)
  155. if sdata[".type"] ~= "ss_server" and n == "server" then
  156. fv = '<a class="label" href="%s">%s</a>' % {
  157. ds.build_url("admin/services/shadowsocks-libev/servers", v), fv}
  158. end
  159. line = n .. ": " .. fv
  160. table.insert(lines, line)
  161. end
  162. end
  163. end
  164. function option_install_package(s, tab)
  165. local bin = s.sectiontype:gsub("_", "-", 1)
  166. local installed = nixio.fs.access("/usr/bin/" .. bin)
  167. if installed then
  168. return
  169. end
  170. local opkg_package = "shadowsocks-libev-" .. bin
  171. local p_install
  172. if tab then
  173. p_install = s:taboption(tab, Button, "_install")
  174. else
  175. p_install = s:option(Button, "_install")
  176. end
  177. p_install.title = translate("Package is not installed")
  178. p_install.inputtitle = translate("Install package %q" % opkg_package)
  179. p_install.inputstyle = "apply"
  180. function p_install.write()
  181. return luci.http.redirect(
  182. luci.dispatcher.build_url("admin/system/packages") ..
  183. "?submit=1&install=%s" % opkg_package
  184. )
  185. end
  186. end
  187. names_options_server = {
  188. "server",
  189. "server_port",
  190. "method",
  191. "key",
  192. "password",
  193. }
  194. names_options_client = {
  195. "server",
  196. "local_address",
  197. "local_port",
  198. }
  199. names_options_common = {
  200. "verbose",
  201. "ipv6_first",
  202. "fast_open",
  203. "reuse_port",
  204. "mode",
  205. "mtu",
  206. "timeout",
  207. "user",
  208. }
  209. modes = {
  210. "tcp_only",
  211. "tcp_and_udp",
  212. "udp_only",
  213. }
  214. methods = {
  215. -- aead
  216. "aes-128-gcm",
  217. "aes-192-gcm",
  218. "aes-256-gcm",
  219. "chacha20-ietf-poly1305",
  220. "xchacha20-ietf-poly1305",
  221. -- stream
  222. "table",
  223. "rc4",
  224. "rc4-md5",
  225. "aes-128-cfb",
  226. "aes-192-cfb",
  227. "aes-256-cfb",
  228. "aes-128-ctr",
  229. "aes-192-ctr",
  230. "aes-256-ctr",
  231. "bf-cfb",
  232. "camellia-128-cfb",
  233. "camellia-192-cfb",
  234. "camellia-256-cfb",
  235. "salsa20",
  236. "chacha20",
  237. "chacha20-ietf",
  238. }