Merge Mainline

This commit is contained in:
CN_SZTL 2021-01-23 21:48:23 +08:00
commit 9d0065ef2e
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
107 changed files with 2940 additions and 3389 deletions

View File

@ -12,8 +12,8 @@ include $(INCLUDE_DIR)/version.mk
include $(INCLUDE_DIR)/feeds.mk
PKG_NAME:=base-files
PKG_RELEASE:=218
PKG_FLAGS:=nonshared
PKG_RELEASE:=$(COMMITCOUNT)
PKG_FILE_DEPENDS:=$(PLATFORM_DIR)/ $(GENERIC_PLATFORM_DIR)/base-files/
PKG_BUILD_DEPENDS:=usign/host ucert/host

View File

@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=uboot-envtools
PKG_DISTNAME:=u-boot
PKG_VERSION:=2020.04
PKG_RELEASE:=17
PKG_RELEASE:=$(AUTORELEASE)
PKG_SOURCE:=$(PKG_DISTNAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:= \

View File

@ -8,12 +8,13 @@
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Luci for JD dailybonus Script
LUCI_DEPENDS:=+node +node-request +coreutils +coreutils-nohup +wget
LUCI_DEPENDS:=+coreutils +coreutils-nohup +node +node-request \
+lua +luasocket +lua-cjson +lua-md5 +luasec +wget-ssl
LUCI_PKGARCH:=all
PKG_NAME:=luci-app-jd-dailybonus
PKG_VERSION:=0.8.9
PKG_RELEASE:=20201230
PKG_VERSION:=1.0.1
PKG_RELEASE:=20210123
include $(TOPDIR)/feeds/luci/luci.mk

File diff suppressed because one or more lines are too long

View File

@ -1,82 +1,112 @@
-- Copyright (C) 2020 jerrykuku <jerrykuku@gmail.com>
-- Licensed to the public under the GNU General Public License v3.
module("luci.controller.jd-dailybonus", package.seeall)
function index()
if not nixio.fs.access("/etc/config/jd-dailybonus") then
return
module('luci.controller.jd-dailybonus', package.seeall)
package.path = package.path .. ';/usr/share/jd-dailybonus/?.lua'
function index()
if not nixio.fs.access('/etc/config/jd-dailybonus') then
return
end
entry({"admin", "services", "jd-dailybonus"}, alias("admin", "services", "jd-dailybonus", "client"), _("JD-DailyBonus"), 10).dependent = true -- 首页
entry({"admin", "services", "jd-dailybonus", "client"}, cbi("jd-dailybonus/client"),_("Client"), 10).leaf = true -- 基本设置
entry({"admin", "services", "jd-dailybonus", "log"},form("jd-dailybonus/log"),_("Log"), 30).leaf = true -- 日志页面
entry({"admin", "services", "jd-dailybonus", "script"},form("jd-dailybonus/script"),_("Script"), 20).leaf = true -- 直接配置脚本
entry({"admin", "services", "jd-dailybonus", "run"}, call("run")) -- 执行程序
entry({"admin", "services", "jd-dailybonus", "update"}, call("update")) -- 执行更新
entry({"admin", "services", "jd-dailybonus", "check_update"}, call("check_update")) -- 检查更新
entry({'admin', 'services', 'jd-dailybonus'}, alias('admin', 'services', 'jd-dailybonus', 'client'), _('京东签到服务'), 10).dependent = true -- 首页
entry({'admin', 'services', 'jd-dailybonus', 'client'}, cbi('jd-dailybonus/client', {hidesavebtn = true, hideresetbtn = true}), _('客户端'), 10).leaf = true -- 基本设置
entry({'admin', 'services', 'jd-dailybonus', 'log'}, form('jd-dailybonus/log'), _('日志'), 30).leaf = true -- 日志页面
entry({'admin', 'services', 'jd-dailybonus', 'script'}, form('jd-dailybonus/script'), _('脚本查看'), 20).leaf = true -- 直接配置脚本
entry({'admin', 'services', 'jd-dailybonus', 'run'}, call('run')) -- 执行程序
entry({'admin', 'services', 'jd-dailybonus', 'update'}, call('update')) -- 执行更新
entry({'admin', 'services', 'jd-dailybonus', 'check_update'}, call('check_update')) -- 检查更新
entry({'admin', 'services', 'jd-dailybonus', 'qrcode'}, call('qrcode')) -- 获取二维码
entry({'admin', 'services', 'jd-dailybonus', 'check_login'}, call('check_login')) -- 获取二维码
end
-- 写入配置
function write_json(file, content)
local json = require 'luci.jsonc'
local f = assert(io.open(file, 'w'))
f:write(json.stringify(content, 1))
f:close()
end
-- 执行程序
function run()
local e = {}
local uci = luci.model.uci.cursor()
local cookie = luci.http.formvalue("cookies")
local cookie2 = luci.http.formvalue("cookies2")
local auto_update = luci.http.formvalue("auto_update")
local auto_update_time = luci.http.formvalue("auto_update_time")
local auto_run = luci.http.formvalue("auto_run")
local auto_run_time = luci.http.formvalue("auto_run_time")
local stop = luci.http.formvalue("stop")
local serverchan = luci.http.formvalue("serverchan")
local failed = luci.http.formvalue("failed")
local name = ""
uci:foreach("vssr", "global", function(s) name = s[".name"] end)
local data = luci.http.formvalue()
if cookie ~= " " then
uci:set("jd-dailybonus", '@global[0]', 'auto_update', auto_update)
uci:set("jd-dailybonus", '@global[0]', 'auto_update_time', auto_update_time)
uci:set("jd-dailybonus", '@global[0]', 'auto_run', auto_run)
uci:set("jd-dailybonus", '@global[0]', 'auto_run_time', auto_run_time)
uci:set("jd-dailybonus", '@global[0]', 'stop', stop)
uci:set("jd-dailybonus", '@global[0]', 'cookie', cookie)
uci:set("jd-dailybonus", '@global[0]', 'cookie2', cookie2)
uci:set("jd-dailybonus", '@global[0]', 'serverchan', serverchan)
uci:set("jd-dailybonus", '@global[0]', 'failed', failed)
uci:save("jd-dailybonus")
uci:commit("jd-dailybonus")
luci.sys.call("/usr/share/jd-dailybonus/newapp.sh -r")
luci.sys.call("/usr/share/jd-dailybonus/newapp.sh -a")
e.error = 0
else
e.error = 1
end
data.auto_run = data.auto_run ~= nil and data.auto_run or 0
data.auto_update = data.auto_update ~= nil and data.auto_update or 0
uci:tset('jd-dailybonus', '@global[0]', data)
uci:commit('jd-dailybonus')
local json_data = {
CookieJD = data.cookie,
CookieJD2 = data.cookie2:len() == 0 and nil or data.cookie2,
JD_DailyBonusDelay = data.stop,
JD_DailyBonusTimeOut = data.out
}
write_json('/root/CookieSet.json', json_data)
write_json('/www/CookieSet.json', json_data)
luci.sys.call('/usr/share/jd-dailybonus/newapp.sh -r')
luci.sys.call('/usr/share/jd-dailybonus/newapp.sh -a')
e.error = 0
luci.http.prepare_content("application/json")
luci.http.prepare_content('application/json')
luci.http.write_json(e)
end
--检查更新
function check_update()
local jd = "jd-dailybonus"
local jd = 'jd-dailybonus'
local e = {}
local new_version = luci.sys.exec("/usr/share/jd-dailybonus/newapp.sh -n")
local new_version = luci.sys.exec('/usr/share/jd-dailybonus/newapp.sh -n')
e.new_version = new_version
e.error = 0
luci.http.prepare_content("application/json")
luci.http.prepare_content('application/json')
luci.http.write_json(e)
end
--执行更新
function update()
local jd = "jd-dailybonus"
local jd = 'jd-dailybonus'
local e = {}
local uci = luci.model.uci.cursor()
local version = luci.http.formvalue("version")
local version = luci.http.formvalue('version')
--下载脚本
local code = luci.sys.exec("/usr/share/jd-dailybonus/newapp.sh -u")
local code = luci.sys.exec('/usr/share/jd-dailybonus/newapp.sh -u')
e.error = code
luci.http.prepare_content("application/json")
luci.http.prepare_content('application/json')
luci.http.write_json(e)
end
end
--获取二维码
function qrcode()
local jd_cookie = require 'jd_cookie'
local e = {}
e.error = 0
e.data = jd_cookie.get_qrcode()
luci.http.prepare_content('application/json')
luci.http.write_json(e)
end
--检测登录
function check_login()
local jd_cookie = require 'jd_cookie'
local uci = luci.model.uci.cursor()
local data = luci.http.formvalue()
local id = data.id
local e = jd_cookie.checkLogin(data.check_url, data.cookies)
if e.error == 0 then
local cookieStr = 'pt_key=' .. e.cookie.pt_key .. ';pt_pin=' .. e.cookie.pt_pin .. ';'
uci:set('jd-dailybonus', '@global[0]', id, cookieStr)
local json_data = {
CookieJD = uci:get('jd-dailybonus', '@global[0]', 'cookie'),
CookieJD2 = uci:get('jd-dailybonus', '@global[0]', 'cookie2'),
JD_DailyBonusDelay = uci:get('jd-dailybonus', '@global[0]', 'stop'),
JD_DailyBonusTimeOut = uci:get('jd-dailybonus', '@global[0]', 'out')
}
write_json('/root/CookieSet.json', json_data)
write_json('/www/CookieSet.json', json_data)
uci:commit('jd-dailybonus')
e.cstr = cookieStr
end
luci.http.prepare_content('application/json')
luci.http.write_json(e)
end

View File

@ -1,75 +1,101 @@
local jd = "jd-dailybonus"
local jd = 'jd-dailybonus'
local uci = luci.model.uci.cursor()
local sys = require "luci.sys"
local sys = require 'luci.sys'
m = Map(jd)
-- [[ 基本设置 ]]--
s = m:section(TypedSection, "global",
translate("Base Config"))
s = m:section(TypedSection, 'global', translate('基本设置'))
s.anonymous = true
o = s:option(DummyValue, "", "")
o = s:option(DummyValue, '', '')
o.rawhtml = true
o.template = "jd-dailybonus/cookie_tools"
o.template = 'jd-dailybonus/cookie_tools'
o = s:option(ListValue, "remote_url", translate("Source Update Url"))
o:value("https://cdn.jsdelivr.net/gh/NobyDa/Script/JD-DailyBonus/JD_DailyBonus.js", translate("GitHub"))
o:value("https://gitee.com/jerrykuku/staff/raw/master/JD_DailyBonus.js", translate("Gitee"))
o.default = "nil"
o.rmempty = false
o.description = translate('当GitHub源无法更新时,可以选择使用国内Gitee源')
o = s:option(Value, "cookie", translate("First Cookie"))
o = s:option(Value, 'cookie', translate('第一账号Cookie'))
o.rmempty = false
o = s:option(Value, "cookie2", translate("Second Cookie"))
o = s:option(Value, 'cookie2', translate('第二账号Cookie'))
o.rmempty = true
o.description = translate('双账号用户抓取"账号1"Cookie后, 请勿点击退出账号(可能会导致Cookie失效), 需清除浏览器资料或更换浏览器登录"账号2"抓取.')
o = s:option(Value, "stop", translate("Execute Delay"))
o = s:option(Value, 'stop', translate('延迟签到'))
o.rmempty = false
o.default = 0
o.datatype = integer
o.description = translate("自定义延迟签到,单位毫秒. 默认分批并发无延迟. (延迟作用于每个签到接口, 如填入延迟则切换顺序签到. ) ")
o.description = translate('自定义延迟签到,单位毫秒. 默认分批并发无延迟. (延迟作用于每个签到接口, 如填入延迟则切换顺序签到. ) ')
o = s:option(ListValue, "serverurl", translate("ServerURL"))
o:value("scu", translate("SCU"))
o:value("sct", translate("SCT"))
o.default = "scu"
o = s:option(Value, 'out', translate('接口超时'))
o.rmempty = false
o.default = 0
o.datatype = integer
o.description = translate('接口超时退出,单位毫秒 用于可能发生的网络不稳定, 0则关闭.')
-- server chan
o = s:option(ListValue, 'serverurl', translate('Server酱的推送接口地址'))
o:value('scu', translate('SCU'))
o:value('sct', translate('SCT'))
o.default = 'scu'
o.rmempty = false
o.description = translate('选择Server酱的推送接口')
o = s:option(Value, "serverchan", translate("ServerChan SCKEY"))
o = s:option(Value, 'serverchan', translate('Server酱 SCKEY'))
o.rmempty = true
o.description = translate("微信推送基于Server酱服务请自行登录 http://sc.ftqq.com/ 绑定并获取 SCKEY (仅在自动签到时推送)")
o.description = translate('微信推送基于Server酱服务请自行登录 http://sc.ftqq.com/ 绑定并获取 SCKEY。')
o = s:option(Flag, "failed", translate("Failed Push"))
-- telegram
o = s:option(Value, 'tg_token', translate('Telegram Bot Token'))
o.rmempty = true
o.description = translate('首先在Telegram上搜索BotFather机器人创建一个属于自己的通知机器人并获取Token。')
o = s:option(Value, 'tg_userid', translate('Telegram UserID'))
o.rmempty = true
o.description = translate('在Telegram上搜索getuserIDbot机器人获取UserID。')
--Auto Run Script Service
o = s:option(Flag, 'auto_run', translate('自动签到'))
o.rmempty = false
o.description = translate("仅当cookie失效时推送")
o = s:option(Flag, "auto_update", translate("Auto Update"))
o.rmempty = false
o.description = translate("Auto Update Script Service")
o =s:option(ListValue, "auto_update_time", translate("Update time (every day)"))
for t = 0, 23 do o:value(t, t .. ":01") end
o = s:option(ListValue, 'auto_run_time_h', translate('每天签到时间(小时)'))
for t = 0, 23 do
o:value(t, t)
end
o.default = 1
o.rmempty = true
o:depends("auto_update", "1")
o = s:option(Flag, "auto_run", translate("Auto Run"))
o.rmempty = false
o.description = translate("Auto Run Script Service")
o =s:option(ListValue, "auto_run_time", translate("Run time (every day)"))
for t = 0, 23 do o:value(t, t .. ":05") end
o:depends('auto_run', '1')
o = s:option(ListValue, 'auto_run_time_m', translate('每天签到时间(分钟)'))
for t = 0, 59 do
o:value(t, t)
end
o.default = 1
o.rmempty = true
o:depends("auto_run", "1")
o:depends('auto_run', '1')
o = s:option(DummyValue, "", "")
-- Auto Update Script Service
o = s:option(Flag, 'auto_update', translate('自动更新'))
o.rmempty = false
o = s:option(ListValue, 'auto_update_time', translate('每天更新时间'))
for t = 0, 23 do
o:value(t, t .. ':01')
end
o.default = 1
o.rmempty = true
o:depends('auto_update', '1')
o = s:option(Value, 'remote_url', translate('更新源地址'))
o:value('https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js', translate('GitHub'))
o:value('https://cdn.jsdelivr.net/gh/NobyDa/Script/JD-DailyBonus/JD_DailyBonus.js', translate('GitHub CDN'))
o:value('https://gitee.com/jerrykuku/staff/raw/master/JD_DailyBonus.js', translate('Gitee'))
o.default = 'nil'
o.rmempty = false
o.description = translate('当GitHub源无法更新时,可以选择使用国内Gitee源,GitHub CDN可能比原地址更晚更新但速度快')
o = s:option(DummyValue, '', '')
o.rawhtml = true
o.version = sys.exec('uci get jd-dailybonus.@global[0].version')
o.template = "jd-dailybonus/update_service"
o.template = 'jd-dailybonus/update_service'
return m

View File

@ -1,25 +1,13 @@
<%+cbi/valueheader%>
<label class="cbi-value-title"><%= translate("Cookie Tools") %></label>
<label class="cbi-value-title"><%= translate("获取Cookie") %></label>
<div class="cbi-value-field">
<input type="button" class="cbi-button cbi-input-reload" value="<%= translate('JDCookie Tools') %>" onclick="javascript:window.open('/jd-dailybonus/JDCookie.zip','target');" />
<input type="button" data-rel="1" class="cbi-button cbi-input-reload cookie-button" value="<%= translate('获取第一Cookie') %>" />
<input type="button" data-rel="2" class="cbi-button cbi-input-reload cookie-button" value="<%= translate('获取第二Cookie') %>" />
<br>
<div class="cbi-value-description">
<span class="cbi-value-helpicon"><img src="/luci-static/resources/cbi/help.gif" alt="帮助"></span>
<%= translate("Click to download the JDCookie.zip,unzip it,and use load Unpacked extensions to install.link:[chrome://extensions/]")%>
</div>
</div>
<%+cbi/valuefooter%>
<%+cbi/valueheader%>
<label class="cbi-value-title"><%= translate("JD Url") %></label>
<div class="cbi-value-field">
<input type="button" class="cbi-button cbi-input-reload" value="bean.m.jd.com" onclick="javascript:window.open('https://bean.m.jd.com','target');" />
<br>
<div class="cbi-value-description">
<span class="cbi-value-helpicon"><img src="/luci-static/resources/cbi/help.gif" alt="帮助"></span>
<%= translate("Sign in ,then click JDCookie button.you will copy JD cookies, paste the cookie below.")%>
<%= translate("点击上面按钮使用京东手机app扫码获取Cookie")%>
</div>
</div>

View File

@ -1,5 +1,9 @@
<%+cbi/valueheader%>
<script src="/jd-dailybonus/jquery.min.js"></script>
<script src="/jd-dailybonus/qrcode.min.js"></script>
<script type="text/javascript">
var jq=$.noConflict();
</script>
<style>
.modals-bg {
position: fixed;
@ -9,7 +13,8 @@
left: 0;
top: 0;
background: rgba(255, 255, 255, 0.8);
display: none;
transition: all 0.3s ease-in-out;
transform: scale(1);
}
.modals {
@ -29,7 +34,22 @@
/* Firefox */
-webkit-box-sizing: border-box;
/* Safari */
transition: all 0.3s ease-in-out;
transform: scale(1);
}
.modals-bg.hide {
visibility: hidden;
opacity: 0;
}
.modals.hide {
visibility: hidden;
opacity: 0;
transform: scale(0.5);
}
.modals h2 {
color: #fff;
@ -72,6 +92,70 @@
text-align: left;
display: table-cell;
}
#qrcontainer {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: 5000;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, .8);
text-align: center;
transition: all 0.3s;
}
#qrcontainer.hidden{
opacity: 0;
visibility: hidden;
}
#qrcontainer .qframe {
background-color: #ffffff;
padding: 1rem;
border-radius: 0.5rem;
border: #6D8A88 1px solid;
-webkit-box-shadow: 0px 0px 7px 3px rgba(0, 0, 0, 0.2);
box-shadow: 0px 0px 7px 3px rgba(0, 0, 0, 0.2);
position: relative;
}
#qrcontainer .qframe #refresh_qrcode{
width: 256px;
height: 256px;
position: absolute;
background-color: rgba(0, 0, 0, 0.5);
left: 1rem;
top: 1rem;
color: #ffffff;
display: flex;
justify-content: center;
align-items: center;
}
#qrcontainer .qframe #refresh_qrcode.hidden{
opacity: 0;
visibility: hidden;
}
#qrcontainer .qframe #refresh_qrcode h3{
font-weight: normal;
}
#qrcontainer .qframe #refresh_qrcode .refresh{
display: block;
background: #e4393c;
width: 80px;
height: 30px;
margin: 0 auto;
line-height: 30px;
opacity: 1;
z-index: 19;
color: #fbfbfb;
text-decoration: none;
cursor: pointer;
}
#qrcontainer .qframe .info {
padding: 1rem 0 0 0;
}
@media screen and (max-width: 1024px) {
.modals {
@ -104,48 +188,54 @@
}
</style>
<label class="cbi-value-title"><%= translate("Run") %></label>
<label class="cbi-value-title"><%= translate("执行") %></label>
<div class="cbi-value-field">
<input class="cbi-button cbi-button-reload" id="update_service" type="button" size="0"
value="<%= translate("Save Cookies And Run Service") %>">
value="<%= translate("保存Cookie,并马上进行签到") %>">
</div>
<%+cbi/valuefooter%>
<%+cbi/valueheader%>
<label class="cbi-value-title"><%= translate("Current Script Version") %></label>
<div class="cbi-value-field">
<div class="cbi-value-version">
v<%=self.version%>
</div>
</div>
<%+cbi/valuefooter%>
<%+cbi/valueheader%>
<label class="cbi-value-title"><%= translate("Update Script") %></label>
<label class="cbi-value-title"><%= translate("更新脚本") %></label>
<div class="cbi-value-field">
<input class="cbi-button cbi-button-reload" id="update_script" type="button" size="0"
value="<%= translate("Check Script Version") %>">
value="<%= translate("手动检查脚本更新当前版本v")..self.version %>">
</div>
<%+cbi/valuefooter%>
<div id="qrcontainer" class="hidden">
<div class="qframe">
<div id="refresh_qrcode" class="hidden">
<div>
<h3>二维码已失效</h3>
<div class="refresh">刷新</div>
</div>
</div>
<div id="qrcode"></div>
<div class="info">请使用京东手机APP扫码</div>
</div>
</div>
<script type="text/javascript">
const SAVE_URL = '<%=luci.dispatcher.build_url("admin", "services", "jd-dailybonus","run")%>';
const CHECK_URL = '<%=luci.dispatcher.build_url("admin", "services", "jd-dailybonus","check_update")%>';
const QRCODE_URL = '<%=luci.dispatcher.build_url("admin", "services", "jd-dailybonus","qrcode")%>';
const CHECK_LOGIN_URL = '<%=luci.dispatcher.build_url("admin", "services", "jd-dailybonus","check_login")%>';
const UPDATE_URL = '<%=luci.dispatcher.build_url("admin", "services", "jd-dailybonus","update")%>';
const CHECKING_TEXT = '<%= translate("Checking the New Version ...") %>';
const UPDATING_TEXT = '<%= translate("Updating script,please wait ...") %>';
const NEW_VERSION = '<%= translate("Is currently the latest version") %>';
const UPDATE_TEXT = '<%= translate("There is a new version, click to update") %>';
const CHECKING_TEXT = '<%= translate("正在检查是否存在新的版本 ...") %>';
const UPDATING_TEXT = '<%= translate("正在更新脚本,请稍候 ...") %>';
const NEW_VERSION = '<%= translate("当前已是最新版本。") %>';
const UPDATE_TEXT = '<%= translate("有新的版本,请点击更新") %>';
var needUpdate = false;
var newVersion;
var _responseLen;
var noChange = 0;
var modal = '<div class="modals-bg">' +
'<div class="modals">' +
var ckid = 0;
var modal = '<div class="modals-bg hide">' +
'<div class="modals hide">' +
'<h2><%:Sign in info%></h2>' +
'<h3 style="margin-left:0;"><%:Service is running,Please do not refresh!%></h3>' +
'<textarea cols="63" rows="28" wrap="on" readonly="readonly" id="log_content3" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>' +
@ -154,52 +244,38 @@
//显示并开始刷新订阅
function update_service() {
$("body").append(modal);
$(".modals-bg").show();
setTimeout("get_realtime_log();", 500);
jq("body").append(modal);
jq(".modals-bg").removeClass("hide");
setTimeout(function(){
jq(".modals").removeClass("hide");
}, 100);
setTimeout("get_realtime_log();", 500);
}
//保存订阅按钮
$("#update_service").click(function () {
prefix_array = $("#cbi-jd-dailybonus-global .cbi-section-node").attr("id").split("-");
prefix = prefix_array[prefix_array.length - 1];
//console.log(prefix);
if ($("[name='cbid.jd-dailybonus." + prefix + ".auto_update']").is(":checked")) {
var auto_update = "1";
var auto_update_time = $("[name='cbid.jd-dailybonus." + prefix + ".auto_update_time']").val();
} else {
var auto_update = "0";
var auto_update_time = "0";
}
if ($("[name='cbid.jd-dailybonus." + prefix + ".auto_run']").is(":checked")) {
var auto_run = "1";
var auto_run_time = $("[name='cbid.jd-dailybonus." + prefix + ".auto_run_time']").val();
} else {
var auto_run = "0";
var auto_run_time = "0";
}
var stop = $("[name='cbid.jd-dailybonus." + prefix + ".stop']").val();
var cookies = $("[name='cbid.jd-dailybonus." + prefix + ".cookie']").val();
var cookies2 = $("[name='cbid.jd-dailybonus." + prefix + ".cookie2']").val();
var failed=($("[name='cbid.jd-dailybonus." + prefix + ".failed']").is(":checked"))?"1":"0";
var serverchan = $("[name='cbid.jd-dailybonus." + prefix + ".serverchan']").val();
var data = {
auto_update: auto_update,
auto_update_time: auto_update_time,
auto_run: auto_run,
auto_run_time: auto_run_time,
cookies: cookies,
cookies2: cookies2,
stop: stop,
serverchan: serverchan,
failed: failed
}
//console.log(data);
$.ajax({
jq("#update_service").click(function () {
let prefix_array = jq(".cbi-input-text").eq(0).attr("id").split(".");
prefix_array.pop()
var prefix = prefix_array.join(".")+".";
let array = jq("form[name*='cbi'").serializeArray()
var json = {};
jq.each(array, function () {
if(this.name.indexOf(prefix) != -1){
let aname = this.name.replace(prefix, "");
if (json[aname]) {
if (!json[aname].push) {
json[aname] = [json[aname]];
}
json[aname].push(this.value || '');
} else {
json[aname] = this.value || '';
}
}
});
jq.ajax({
type: "post",
url: SAVE_URL,
dataType: "json",
data: data,
data: json,
success: function (d) {
if (d.error == 0) {
update_service();
@ -212,29 +288,29 @@
});
//更新脚本
$("#update_script").click(function () {
jq("#update_script").click(function () {
check_version()
return false;
});
function updateS(){
$("#update_script").attr("disabled", true);
$("#update_script").val(UPDATING_TEXT);
jq("#update_script").attr("disabled", true);
jq("#update_script").val(UPDATING_TEXT);
//console.log(data);
var data = {
version: $("#update_script").attr("data-version")
version: jq("#update_script").attr("data-version")
}
$.ajax({
jq.ajax({
type: "post",
url: UPDATE_URL,
dataType: "json",
data: data,
success: function (d) {
if (d.error == 0) {
$("#update_script").val(NEW_VERSION);
$(".cbi-value-version").text("v" + newVersion);
jq("#update_script").val(NEW_VERSION);
jq(".cbi-value-version").text("v" + newVersion);
} else {
$("#update_script").attr("disabled", false);
jq("#update_script").attr("disabled", false);
alert("更新错误请重试");
}
}
@ -243,7 +319,7 @@
function get_realtime_log() {
$.ajax({
jq.ajax({
url: '/JD_DailyBonus.htm?v=' + parseInt(Math.random() * 100000000),
dataType: 'html',
error: function (xhr) {
@ -272,9 +348,9 @@
}
function check_version() {
$("#update_script").attr("disabled", true);
$("#update_script").val(CHECKING_TEXT);
$.ajax({
jq("#update_script").attr("disabled", true);
jq("#update_script").val(CHECKING_TEXT);
jq.ajax({
url: CHECK_URL,
dataType: 'json',
error: function (xhr) {
@ -282,20 +358,94 @@
},
success: function (data) {
if(data.new_version == 501){
$("#update_script").attr("disabled", false);
$("#update_script").val("无法获取新版本,请重试!");
jq("#update_script").attr("disabled", false);
jq("#update_script").val("无法获取新版本,请重试!");
}else if (data.new_version > <%= self.version %>) {
$("#update_script").attr("disabled", false);
$("#update_script").val(UPDATE_TEXT + " v" + data.new_version);
$("#update_script").attr("data-version", data.new_version);
jq("#update_script").attr("disabled", false);
jq("#update_script").val(UPDATE_TEXT + " v" + data.new_version);
jq("#update_script").attr("data-version", data.new_version);
newVersion = data.new_version;
updateS();
} else {
$("#update_script").val(NEW_VERSION + " v" + data.new_version);
updateS();
jq("#update_script").val(NEW_VERSION + " v" + data.new_version);
}
}
}
});
}
qrcode = new QRCode(document.getElementById("qrcode"),
{
text: "sample",
correctLevel: QRCode.CorrectLevel.L
});
//获取二维码
function get_code() {
let timeStamp = (new Date()).getTime()
$.get('/qrcode?t='+timeStamp, function (data) {
if (data.err == 0) {
jq("#qrcontainer").removeClass("hidden")
jq("#refresh_qrcode").addClass("hidden")
qrcode.clear();
qrcode.makeCode(data.qrcode);
checkLogin();
} else {
Swal.fire({
text: data.msg,
icon: "error"
})
}
});
}
jq(".cookie-button").click(function(){
ckid = jq(this).attr("data-rel");
get_code()
return false;
})
jq('.refresh').click(get_code);
function get_code(){
let timeStamp = (new Date()).getTime()
jq.ajax({
url: QRCODE_URL+"?t="+timeStamp,
dataType: 'json',
success: function (data) {
if(data.error == 0){
jq("#qrcontainer").removeClass("hidden")
jq("#refresh_qrcode").addClass("hidden")
console.log(data.data.qrcode_url)
qrcode.clear();
qrcode.makeCode(data.data.qrcode_url);
checkLogin(data.data.check_url,data.data.cookies);
} else {
alert("出错了请重试。")
}
}
});
return false;
}
function checkLogin(check_url,cookies){
var timeId = setInterval(() => {
let cname = ckid == 1?"cookie":"cookie2"
jq.post( CHECK_LOGIN_URL, { check_url:check_url,cookies: cookies ,id: cname}, function( data ) {
if (data.error == 0) {
clearInterval(timeId)
jq("#qrcontainer").addClass("hidden")
jq("#refresh_qrcode").addClass("hidden")
let prefix_array = jq(".cbi-input-text").eq(0).attr("id").split(".");
prefix_array.pop()
let prefix = prefix_array.join(".")+".";
console.log("."+prefix+cname,data.cstr);
document.getElementById(prefix+cname).value =data.cstr
} else if (data.error == 21 || data.error == 261) {
clearInterval(timeId)
jq("#refresh_qrcode").removeClass("hidden")
}
}, "json");
}, 3000)
}
</script>

View File

@ -1,111 +0,0 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\n"
msgid "JD-DailyBonus"
msgstr "京东签到服务"
msgid "Enable"
msgstr "启用"
msgid "Disable"
msgstr "停用"
msgid "Log"
msgstr "日志"
msgid "Script"
msgstr "脚本"
msgid "Base Config"
msgstr "基本设置"
msgid "Cookie Tools"
msgstr "Cookie 工具"
msgid "JDCookie Tools"
msgstr "获取京东cookie扩展工具"
msgid "Source Update Url"
msgstr "更新源地址"
msgid "First Cookie"
msgstr "主账号Cookie"
msgid "Second Cookie"
msgstr "第二账号Cookie"
msgid "Click to download the JDCookie.zip,unzip it,and use load Unpacked extensions to install.link:[chrome://extensions/]")"
msgstr "点击上面的按钮安装下载JDCookie.zip获取京东cookie扩展工具解压后在[chrome://extensions/]中使用加载已解压的扩展程序进行安装。 "
msgid "JD Url"
msgstr "京东链接"
msgid "Sign in ,then click JDCookie button.you will copy JD cookies, paste the cookie below."
msgstr "登录后点击JDCookie 扩展工具复制cookie然后粘贴到下面输入框中。请使用F12调试工具进入模拟手机浏览器模式"
msgid "Auto Update Script Service"
msgstr "自动更新脚本服务"
msgid "Update time (every day)"
msgstr "更新时间 (每天)"
msgid "Update Script"
msgstr "更新脚本"
msgid "Execute Delay"
msgstr "延迟签到"
msgid "ServerChan SCKEY"
msgstr "Server酱 SCKEY"
msgid "ServerURL"
msgstr "Server酱的推送接口地址"
msgid "SCT"
msgstr "测试版推送接口地址"
msgid "SCU"
msgstr "原版推送接口地址"
msgid "Failed Push"
msgstr "失效时推送"
msgid "Auto Run"
msgstr "自动签到"
msgid "Run"
msgstr "执行"
msgid "Auto Run Script Service"
msgstr "自动签到服务"
msgid "Run time (every day)"
msgstr "签到时间 (每天)"
msgid "Save Cookies And Run Service"
msgstr "保存Cookie并签到"
msgid "Sign in info"
msgstr "签到信息"
msgid "Service is running,Please do not refresh!"
msgstr "服务正在执行中,请勿刷新!"
msgid "Updating script,please wait ..."
msgstr "正在更新脚本,请稍候 ..."
msgid "Is currently the latest version"
msgstr "当前已是最新版本。"
msgid "There is a new version, click to update"
msgstr "有新的版本,请点击更新"
msgid "Checking the New Version ..."
msgstr "正在检查是否存在新的版本 ..."
msgid "Check Script Version"
msgstr "手动检查脚本更新"
msgid "Current Script Version"
msgstr "当前脚本版本"

View File

@ -1,9 +1,14 @@
config global
option version '1.87'
option auto_run_time '1'
option auto_run '1'
option auto_update_time '1'
option version '1.90'
option out '0'
option stop '100'
option serverchan ''
option remote_url 'https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js'
option serverurl 'scu'
option auto_update '1'
option stop '0'
option failed '0'
option remote_url 'https://cdn.jsdelivr.net/gh/NobyDa/Script/JD-DailyBonus/JD_DailyBonus.js'
option auto_update_time '23'
option auto_run '1'
option auto_run_time '0'
option auto_run_time_m '1'
option auto_run_time_h '1'
option cookie ''

View File

@ -2,7 +2,7 @@
京东多合一签到脚本
更新时间: 2020.12.25 17:50 v1.89
更新时间: 2021.01.07 17:00 v1.90
有效接口: 40+
脚本兼容: QuantumultX, Surge, Loon, JSBox, Node.js
电报频道: @NobyDa
@ -13,7 +13,7 @@
JSbox, Node.js 说明 :
*************************
开启抓包app后, Safari浏览器登录 https://bean.m.jd.com 点击签到并且出现签到日历后, 返回抓包app搜索关键字 functionId=signBean 复制请求头Cookie填入以下Key处的单引号内即可 */
开启抓包app后, Safari浏览器登录 https://bean.m.jd.com/bean/signIndex.action 点击签到并且出现签到日历后, 返回抓包app搜索关键字 functionId=signBean 复制请求头Cookie填入以下Key处的单引号内即可 */
var Key = ''; //单引号内自行填写您抓取的Cookie
@ -30,7 +30,7 @@ var DualKey = ''; //如需双账号签到,此处单引号内填写抓取的"账
QX, Surge, Loon 说明 :
*************************
初次使用时, app配置文件添加脚本配置,并启用Mitm后, Safari浏览器打开登录 https://bean.m.jd.com ,点击签到并且出现签到日历后, 如果通知获得cookie成功, 则可以使用此签到脚本。 注: 请勿在京东APP内获取!!!
初次使用时, app配置文件添加脚本配置,并启用Mitm后, Safari浏览器打开登录 https://bean.m.jd.com/bean/signIndex.action ,点击签到并且出现签到日历后, 如果通知获得cookie成功, 则可以使用此签到脚本。 注: 请勿在京东APP内获取!!!
由于cookie的有效性(经测试网页Cookie有效周期最长31天)如果脚本后续弹出cookie无效的通知则需要重复上述步骤
签到脚本将在每天的凌晨0:05执行, 您可以修改执行时间 因部分接口京豆限量领取, 建议调整为凌晨签到
@ -108,14 +108,12 @@ async function all() {
case 0:
await Promise.all([
JingDongBean(stop), //京东京豆
JDTakeaLook(stop), //京东发现-看一看
JingDongStore(stop), //京东超市
JingDongWebcasts(stop), //京东直播
JingRongBean(stop), //金融简单赚钱
JingRongSteel(stop), //金融钢镚
JingDongTurn(stop), //京东转盘
JDFlashSale(stop), //京东闪购
JDOverseas(stop), //京东国际
JingDongCash(stop), //京东现金红包
JDMagicCube(stop, 2), //京东小魔方
JingDongSubsidy(stop), //京东金贴
@ -131,15 +129,13 @@ async function all() {
JingRongDoll(stop, 'JRFiveDoll', '京东金融-签伍', '1D06AA3B0F')
]);
await Promise.all([
JDUserSignPre(stop, 'JDClothing', '京东商城-服饰', '4RBT3H9jmgYg1k2kBnHF8NAHm7m8'), //京东服饰
JDUserSignPre(stop, 'JDUnderwear', '京东商城-内衣', '4PgpL1xqPSW1sVXCJ3xopDbB1f69'), //京东内衣馆
JDUserSignPre(stop, 'JDShoes', '京东商城-鞋靴', '4RXyb1W4Y986LJW8ToqMK14BdTD'), //京东鞋靴
JDUserSignPre(stop, 'JDCalendar', '京东日历-翻牌', '36V2Qw59VPNsuLxY84vCFtxFzrFs'), //京东日历翻牌
JDUserSignPre(stop, 'JDChild', '京东商城-童装', '3Af6mZNcf5m795T8dtDVfDwWVNhJ'), //京东童装馆
JDUserSignPre(stop, 'JDBaby', '京东商城-母婴', '3BbAVGQPDd6vTyHYjmAutXrKAos6'), //京东母婴馆
JDUserSignPre(stop, 'JD3C', '京东商城-数码', '4SWjnZSCTHPYjE5T7j35rxxuMTb6'), //京东数码电器馆
JDUserSignPre(stop, 'JDSubsidy', '京东晚市-补贴', 'xK148m4kWj5hBcTPuJUNNXH3AkJ'), //京东晚市补贴金
JDUserSignPre(stop, 'JDDrug', '京东商城-医药', '3tqTG5sF1xCUyC6vgEF5CLCxGn7w'), //京东医药馆
// JDUserSignPre(stop, 'JDSubsidy', '京东晚市-补贴', 'xK148m4kWj5hBcTPuJUNNXH3AkJ'), //京东晚市补贴金
// JDUserSignPre(stop, 'JDDrug', '京东商城-医药', '3tqTG5sF1xCUyC6vgEF5CLCxGn7w'), //京东医药馆
JDUserSignPre(stop, 'JDWomen', '京东商城-女装', 'DpSh7ma8JV7QAxSE2gJNro8Q2h9'), //京东女装馆
JDUserSignPre(stop, 'JDFineWine', '京东商城-酒饮', 'zGwAUzL3pVGjptBBGeYfpKjYdtX'), //京东酒饮馆
JDUserSignPre(stop, 'JDBook', '京东商城-图书', '3SC6rw5iBg66qrXPGmZMqFDwcyXi'), //京东图书
@ -147,15 +143,17 @@ async function all() {
JingRongDoll(stop, 'XJDouble', '金融现金-双签', 'F68B2C3E71', '', '', '', 'xianjin') //京东金融 现金双签
]);
await Promise.all([
JDUserSignPre(stop, 'JDClothing', '京东商城-服饰', '4RBT3H9jmgYg1k2kBnHF8NAHm7m8'), //京东服饰
JDUserSignPre(stop, 'JDUnderwear', '京东商城-内衣', '4PgpL1xqPSW1sVXCJ3xopDbB1f69'), //京东内衣馆
JDUserSignPre(stop, 'JDSuitcase', '京东商城-箱包', 'ZrH7gGAcEkY2gH8wXqyAPoQgk6t'), //京东箱包馆
JDUserSignPre(stop, 'JDSchool', '京东商城-校园', '4812pn2PAcUyfNdWr7Cvpww5MCyW'), //京东校园
JDUserSignPre(stop, 'JDHealth', '京东商城-健康', 'w2oeK5yLdHqHvwef7SMMy4PL8LF'), //京东健康
JDUserSignPre(stop, 'JDPet', '京东商城-宠物', '37ta5sh5ocrMZF3Fz5UMJbTsL42'), //京东宠物馆
JDUserSignPre(stop, 'JDShand', '京东拍拍-二手', '3S28janPLYmtFxypu37AYAGgivfp'), //京东拍拍二手
// JDUserSignPre(stop, 'JDPet', '京东商城-宠物', '37ta5sh5ocrMZF3Fz5UMJbTsL42'), //京东宠物馆
// JDUserSignPre(stop, 'JDShand', '京东拍拍-二手', '3S28janPLYmtFxypu37AYAGgivfp'), //京东拍拍二手
JDUserSignPre(stop, 'JDClean', '京东商城-清洁', '2Tjm6ay1ZbZ3v7UbriTj6kHy9dn6'), //京东清洁馆
JDUserSignPre(stop, 'JDCare', '京东商城-个护', 'NJ1kd1PJWhwvhtim73VPsD1HwY3'), //京东个人护理馆
JDUserSignPre(stop, 'JDJewels', '京东商城-珠宝', 'zHUHpTHNTaztSRfNBFNVZscyFZU'), //京东珠宝馆
JDUserSignPre(stop, 'JDClocks', '京东商城-钟表', '2BcJPCVVzMEtMUynXkPscCSsx68W'), //京东钟表馆
// JDUserSignPre(stop, 'JDClocks', '京东商城-钟表', '2BcJPCVVzMEtMUynXkPscCSsx68W'), //京东钟表馆
JDUserSignPre(stop, 'JDMakeup', '京东商城-美妆', '2smCxzLNuam5L14zNJHYu43ovbAP'), //京东美妆馆
JDUserSignPre(stop, 'JDVege', '京东商城-菜场', 'Wcu2LVCFMkBP3HraRvb7pgSpt64') //京东菜场
]);
@ -164,14 +162,12 @@ async function all() {
break;
default:
await JingDongBean(stop); //京东京豆
await JDTakeaLook(stop); //京东发现-看一看
await JingDongStore(stop); //京东超市
await JingDongWebcasts(stop); //京东直播
await JingRongBean(stop); //金融简单赚钱
await JingRongSteel(stop); //金融钢镚
await JingDongTurn(stop); //京东转盘
await JDFlashSale(stop); //京东闪购
await JDOverseas(stop); //京东国际
await JingDongCash(stop); //京东现金红包
await JDMagicCube(stop, 2); //京东小魔方
await JingDongGetCash(stop); //京东领现金
@ -197,13 +193,13 @@ async function all() {
await JDUserSignPre(stop, 'JDChild', '京东商城-童装', '3Af6mZNcf5m795T8dtDVfDwWVNhJ'); //京东童装馆
await JDUserSignPre(stop, 'JDBaby', '京东商城-母婴', '3BbAVGQPDd6vTyHYjmAutXrKAos6'); //京东母婴馆
await JDUserSignPre(stop, 'JD3C', '京东商城-数码', '4SWjnZSCTHPYjE5T7j35rxxuMTb6'); //京东数码电器馆
await JDUserSignPre(stop, 'JDSubsidy', '京东晚市-补贴', 'xK148m4kWj5hBcTPuJUNNXH3AkJ'); //京东晚市补贴金
await JDUserSignPre(stop, 'JDClocks', '京东商城-钟表', '2BcJPCVVzMEtMUynXkPscCSsx68W'); //京东钟表馆
await JDUserSignPre(stop, 'JDDrug', '京东商城-医药', '3tqTG5sF1xCUyC6vgEF5CLCxGn7w'); //京东医药馆
// await JDUserSignPre(stop, 'JDSubsidy', '京东晚市-补贴', 'xK148m4kWj5hBcTPuJUNNXH3AkJ'); //京东晚市补贴金
// await JDUserSignPre(stop, 'JDClocks', '京东商城-钟表', '2BcJPCVVzMEtMUynXkPscCSsx68W'); //京东钟表馆
// await JDUserSignPre(stop, 'JDDrug', '京东商城-医药', '3tqTG5sF1xCUyC6vgEF5CLCxGn7w'); //京东医药馆
await JDUserSignPre(stop, 'JDWomen', '京东商城-女装', 'DpSh7ma8JV7QAxSE2gJNro8Q2h9'); //京东女装馆
await JDUserSignPre(stop, 'JDPet', '京东商城-宠物', '37ta5sh5ocrMZF3Fz5UMJbTsL42'); //京东宠物馆
// await JDUserSignPre(stop, 'JDPet', '京东商城-宠物', '37ta5sh5ocrMZF3Fz5UMJbTsL42'); //京东宠物馆
await JDUserSignPre(stop, 'JDBook', '京东商城-图书', '3SC6rw5iBg66qrXPGmZMqFDwcyXi'); //京东图书
await JDUserSignPre(stop, 'JDShand', '京东拍拍-二手', '3S28janPLYmtFxypu37AYAGgivfp'); //京东拍拍二手
// await JDUserSignPre(stop, 'JDShand', '京东拍拍-二手', '3S28janPLYmtFxypu37AYAGgivfp'); //京东拍拍二手
await JDUserSignPre(stop, 'JDMakeup', '京东商城-美妆', '2smCxzLNuam5L14zNJHYu43ovbAP'); //京东美妆馆
await JDUserSignPre(stop, 'JDFineWine', '京东商城-酒饮', 'zGwAUzL3pVGjptBBGeYfpKjYdtX'); //京东酒饮馆
await JDUserSignPre(stop, 'JDVege', '京东商城-菜场', 'Wcu2LVCFMkBP3HraRvb7pgSpt64'); //京东菜场
@ -1700,56 +1696,6 @@ function JingRongDoll(s, key, title, code, type, num, award, belong) {
});
}
function JDOverseas(s) {
merge.Overseas = {};
return new Promise(resolve => {
if (disable("Overseas")) return resolve()
setTimeout(() => {
const OverseasUrl = {
url: 'https://api.m.jd.com/client.action?functionId=checkin',
headers: {
Cookie: KEY
},
body: "body=%7B%7D&build=167237&client=apple&clientVersion=9.0.0&openudid=1fce88cd05c42fe2b054e846f11bdf33f016d676&partner=apple&scope=11&sign=e27f8b904040a0e3c99b87fc27e09c87&st=1591730990449&sv=101"
};
$nobyda.post(OverseasUrl, function(error, response, data) {
try {
if (error) {
throw new Error(error)
} else {
const Details = LogDetails ? "response:\n" + data : '';
if (data.match(/\"type\":\d+?,/)) {
console.log("\n" + "京东商城-国际签到成功 " + Details)
merge.Overseas.success = 1
if (data.match(/\"jdBeanAmount\":[1-9]+/)) {
merge.Overseas.bean = data.match(/\"jdBeanAmount\":(\d+)/)[1]
merge.Overseas.notify = "京东商城-国际: 成功, 明细: " + merge.Overseas.bean + "京豆 🐶"
} else {
merge.Overseas.notify = "京东商城-国际: 成功, 明细: 无京豆 🐶"
}
} else {
console.log("\n" + "京东商城-国际签到失败 " + Details)
merge.Overseas.fail = 1
if (data.match(/(\"code\":\"13\"|重复签到)/)) {
merge.Overseas.notify = "京东商城-国际: 失败, 原因: 已签过 ⚠️"
} else if (data.match(/\"code\":\"(-1|3)\"/)) {
merge.Overseas.notify = "京东商城-国际: 失败, 原因: Cookie失效‼"
} else {
merge.Overseas.notify = "京东商城-国际: 失败, 原因: 未知 ⚠️"
}
}
}
} catch (eor) {
$nobyda.AnError("京东商城-国际", "Overseas", eor, response, data)
} finally {
resolve()
}
})
}, s)
if (out) setTimeout(resolve, out + s)
});
}
function JingDongGetCash(s) {
merge.JDGetCash = {};
return new Promise(resolve => {
@ -1834,45 +1780,6 @@ function JingDongWebcasts(s) {
});
}
function JDTakeaLook(s) {
merge.TakeaLook = {};
return new Promise(resolve => {
if (disable("TakeaLook")) return resolve()
setTimeout(() => {
$nobyda.get({
url: 'https://api.m.jd.com/client.action?functionId=discTaskList&body=%7B%22bizType%22%3A1%2C%22referPageId%22%3A%22discRecommend%22%7D&client=apple&clientVersion=9.1.6&openudid=1fce88cd05c42fe2b054e846f11bdf33f016d676&sign=17061147fe8e0eb10edfe8d9968b6d66&st=1601138337675&sv=102',
headers: {
Cookie: KEY
}
}, (error, response, data) => {
try {
if (error) throw new Error(error);
const cc = JSON.parse(data);
const Details = LogDetails ? "response:\n" + data : '';
const tm = parseInt((Date.now() + 28800000) / 86400000) * 86400000 - 28800000
if (data.match(/签到成功/) && !data.match(tm)) {
console.log(`\n京东发现-看看签到成功 ${Details}`)
const aw = data.match(/\"签到成功,获得(\d+)京豆\"/)
merge.TakeaLook.success = 1
merge.TakeaLook.bean = aw ? aw[1] : 0
merge.TakeaLook.notify = `京东发现-看看: 成功, 明细: ${merge.TakeaLook.bean||``}京豆 🐶`
} else {
console.log(`\n京东发现-看看签到失败 ${Details}`)
const tp = data.match(tm) ? `已签过` : cc.busiCode == 2001 ? `Cookie失效` : `${cc.message||`未知`}`
merge.TakeaLook.notify = `京东发现-看看: 失败, 原因: ${tp}${cc.busiCode==2001?`‼️`:` ⚠️`}`
merge.TakeaLook.fail = 1
}
} catch (eor) {
$nobyda.AnError("京东发现-看看", "TakeaLook", eor, response, data)
} finally {
resolve()
}
})
}, s)
if (out) setTimeout(resolve, out + s)
});
}
function JingDongStore(s) {
merge.JDGStore = {};
return new Promise(resolve => {

View File

@ -0,0 +1,168 @@
-- Copyright (C) 2021 jerrykuku <jerrykuku@gmail.com>
-- Licensed to the public under the GNU General Public License v3.
local uci = require 'luci.model.uci'.cursor()
local config = 'jd-dailybonus'
package.path = package.path .. ';/usr/share/jd-dailybonus/?.lua'
local requests = require 'requests'
local socket = require 'socket'
local tinsert = table.insert
local ssub, slen, schar, sbyte, sformat, sgsub = string.sub, string.len, string.char, string.byte, string.format, string.gsub
local User_Agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36'
local Host = 'plogin.m.jd.com'
local jd_cookie = {}
--打印table
function print_r(t)
local print_r_cache = {}
local function sub_print_r(t, indent)
if (print_r_cache[tostring(t)]) then
print(indent .. '*' .. tostring(t))
else
print_r_cache[tostring(t)] = true
if (type(t) == 'table') then
for pos, val in pairs(t) do
if (type(val) == 'table') then
print(indent .. '[' .. pos .. '] => ' .. tostring(t) .. ' {')
sub_print_r(val, indent .. string.rep(' ', string.len(pos) + 8))
print(indent .. string.rep(' ', string.len(pos) + 6) .. '}')
elseif (type(val) == 'string') then
print(indent .. '[' .. pos .. '] => "' .. val .. '"')
else
print(indent .. '[' .. pos .. '] => ' .. tostring(val))
end
end
else
print(indent .. tostring(t))
end
end
end
if (type(t) == 'table') then
print(tostring(t) .. ' {')
sub_print_r(t, ' ')
print('}')
else
sub_print_r(t, ' ')
end
print()
end
-- 分割字符串
local function split(full, sep)
full = full:gsub('%z', '') -- 这里不是很清楚 有时候结尾带个\0
local off, result = 1, {}
while true do
local nStart, nEnd = full:find(sep, off)
if not nEnd then
local res = ssub(full, off, slen(full))
if #res > 0 then -- 过滤掉 \0
tinsert(result, res)
end
break
else
tinsert(result, ssub(full, off, nStart - 1))
off = nEnd + 1
end
end
return result
end
--获取unix时间戳
function jd_cookie.timestamp()
return math.floor(socket.gettime() * 1000)
end
--延时函数
function sleep(n)
os.execute('sleep ' .. n)
end
--解析cookie
function praseSetCookies(rcookie)
local tbl = {}
for k, v in rcookie:gmatch('([^;%s]+)=([^;]+)') do
tbl[k] = v
end
return tbl
end
--获取二维码链接和检测URL
function jd_cookie.get_qrcode()
local timeStamp = jd_cookie.timestamp()
local url =
'https://plogin.m.jd.com/cgi-bin/mm/new_login_entrance?lang=chs&appid=300&returnurl=https://wq.jd.com/passport/LoginRedirect?state=' ..
timeStamp .. '&returnurl=https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport'
local xformHeaders = {
['Content-Type'] = 'application/x-www-form-urlencoded',
['Connection'] = 'Keep-Alive',
['Accept'] = 'application/json, text/plain, */*',
['Accept-Language'] = 'zh-cn',
['Referer'] = 'https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wq.jd.com/passport/LoginRedirect?state=' ..
timeStamp .. '&returnurl=https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport',
['User-Agent'] = User_Agent,
['Host'] = Host
}
local response = requests.get {url, headers = xformHeaders}
local s_token = response.json().s_token
local dat = split(string.gsub(response.headers['set-cookie'], ' DOMAIN=.plogin.m.jd.com', ''), ';')
local cookies = string.gsub(dat[1] .. dat[4] .. dat[6] .. dat[8], ',', ';') .. ';'
local timeStamp = jd_cookie.timestamp()
local url = 'https://plogin.m.jd.com/cgi-bin/m/tmauthreflogurl?s_token=' .. s_token .. '&v=' .. timeStamp .. '&remember=true'
local xformHeaders = {
['Content-Type'] = 'application/x-www-form-urlencoded',
['Connection'] = 'Keep-Alive',
['Accept'] = 'application/json, text/plain, */*',
['Accept-Language'] = 'zh-cn',
['Referer'] = 'https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wq.jd.com/passport/LoginRedirect?state=' ..
timeStamp .. '&returnurl=https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport',
['User-Agent'] = User_Agent,
['Host'] = Host
}
local response = requests.post {url, cookies = cookies, headers = xformHeaders}
local json_body, error = response.json()
local token = json_body['token']
local ou_state = json_body['ou_state']
local okl_token = praseSetCookies(response.headers['set-cookie']).okl_token
local return_json = {
qrcode_url = 'https://plogin.m.jd.com/cgi-bin/m/tmauth?appid=300&client_type=m&token=' .. token,
check_url = 'https://plogin.m.jd.com/cgi-bin/m/tmauthchecktoken?&token=' .. token .. '&ou_state=' .. ou_state .. '&okl_token=' .. okl_token,
cookies = cookies
}
return return_json
end
--检测扫码状态 并返回cookie
function jd_cookie.checkLogin(url, cookies)
local xformHeaders = {
['Content-Type'] = 'application/x-www-form-urlencoded',
['Connection'] = 'Keep-Alive',
['Accept'] = 'application/json, text/plain, */*',
['Accept-Language'] = 'zh-cn',
['Referer'] = 'https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wqlogin2.jd.com/passport/LoginRedirect?state=',
['User-Agent'] = User_Agent,
['Host'] = Host
}
local data =
'lang=chs&appid=300&source=wq_passport&returnurl=https://wqlogin2.jd.com/passport/LoginRedirect?state=1100399130787&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action'
local response = requests.post {url, data = data, cookies = cookies, headers = xformHeaders}
--local cookie = jd_cookie.praseSetCookies(response.headers['set-cookie'])
local json = response.json()
local return_json = {}
if json.errcode == 0 then
local ucookie = praseSetCookies(response.headers['set-cookie'])
return_json = {
error = 0,
cookie = ucookie
}
else
return_json = {
error = json.errcode,
msg = json.message
}
end
return return_json
end
return jd_cookie

View File

@ -49,78 +49,58 @@ cancel() {
exit 1
}
fill_cookie() {
cookie1=$(uci_get_by_type global cookie)
if [ ! "$cookie1" = "" ]; then
varb="var Key = '$cookie1';"
a=$(sed -n '/var Key =/=' $JD_SCRIPT)
b=$((a-1))
sed -i "${a}d" $JD_SCRIPT
sed -i "${b}a ${varb}" $JD_SCRIPT
fi
cookie2=$(uci_get_by_type global cookie2)
if [ ! "$cookie2" = "" ]; then
varb2="var DualKey = '$cookie2';"
aa=$(sed -n '/var DualKey =/=' $JD_SCRIPT)
bb=$((aa-1))
sed -i "${aa}d" $JD_SCRIPT
sed -i "${bb}a ${varb2}" $JD_SCRIPT
fi
stop=$(uci_get_by_type global stop)
if [ ! "$stop" = "" ]; then
varb3="var stop = $stop;"
sed -i "s/^var stop =.*/$varb3/g" $JD_SCRIPT
fi
}
add_cron() {
sed -i '/jd-dailybonus/d' $CRON_FILE
[ $(uci_get_by_type global auto_run 0) -eq 1 ] && echo '5 '$(uci_get_by_type global auto_run_time)' * * * sleep '$(expr $(head -n 128 /dev/urandom | tr -dc "0123456789" | head -c4) % 180)'s; /usr/share/jd-dailybonus/newapp.sh -w' >>$CRON_FILE
[ $(uci_get_by_type global auto_run 0) -eq 1 ] && echo $(uci_get_by_type global auto_run_time_m)' '$(uci_get_by_type global auto_run_time_h)' * * * /usr/share/jd-dailybonus/newapp.sh -w' >>$CRON_FILE
[ $(uci_get_by_type global auto_update 0) -eq 1 ] && echo '1 '$(uci_get_by_type global auto_update_time)' * * * /usr/share/jd-dailybonus/newapp.sh -u' >>$CRON_FILE
crontab $CRON_FILE
/etc/init.d/cron restart
}
# Run Script
serverchan() {
sckey=$(uci_get_by_type global serverchan)
failed=$(uci_get_by_type global failed)
desc=$(cat /www/JD_DailyBonus.htm | grep -E '签到号|签到概览|签到奖励|其他奖励|账号总计|其他总计' | sed 's/$/&\n/g')
serverurlflag=$(uci_get_by_type global serverurl)
serverurl=https://sc.ftqq.com/
if [ "$serverurlflag" = "sct" ]; then
serverurl=https://sctapi.ftqq.com/
fi
if [ $failed -eq 1 ]; then
grep "Cookie失效" /www/JD_DailyBonus.htm > /dev/null
if [ $? -eq 0 ]; then
title="$(date '+%Y年%m月%d日') 京东签到 Cookie 失效"
wget-ssl -q --output-document=/dev/null --post-data="text=$title~&desp=$desc" $serverurl$sckey.send
fi
notify() {
grep "Cookie失效" /www/JD_DailyBonus.htm >/dev/null
if [ $? -eq 0 ]; then
title="$(date '+%Y年%m月%d日') 京东签到 Cookie 失效"
else
title="$(date '+%Y年%m月%d日') 京东签到"
fi
desc=$(cat /www/JD_DailyBonus.htm | grep -E '签到号|签到概览|签到奖励|其他奖励|账号总计|其他总计' | sed 's/$/&\n/g')
#serverchan
sckey=$(uci_get_by_type global serverchan)
if [ ! -z $sckey ]; then
serverurlflag=$(uci_get_by_type global serverurl)
serverurl=https://sc.ftqq.com/
if [ "$serverurlflag" = "sct" ]; then
serverurl=https://sctapi.ftqq.com/
fi
wget-ssl -q --output-document=/dev/null --post-data="text=$title~&desp=$desc" $serverurl$sckey.send
fi
#telegram
TG_BOT_TOKEN=$(uci_get_by_type global tg_token)
TG_USER_ID=$(uci_get_by_type global tg_userid)
API_URL="https://api.telegram.org/bot${TG_BOT_TOKEN}/sendMessage"
if [ ! -z $TG_BOT_TOKEN ] && [ ! -z $TG_USER_ID ]; then
text="*$title*
\`\`\`
"$desc"
====================================
本消息来自京东签到插件 jd-dailybonus
\`\`\`"
wget-ssl -q --output-document=/dev/null --post-data="chat_id=$TG_USER_ID&text=$text&parse_mode=markdownv2" $API_URL
fi
}
run() {
fill_cookie
echo -e $(date '+%Y-%m-%d %H:%M:%S %A') >$LOG_HTM 2>/dev/null
[ ! -f "/usr/bin/node" ] && echo -e "未安装node.js,请安装后再试!\nNode.js is not installed, please try again after installation!">>$LOG_HTM && exit 1
node $JD_SCRIPT >>$LOG_HTM 2>/dev/null
}
back_run() {
run
sleep 1s
serverchan
[ ! -f "/usr/bin/node" ] && echo -e "未安装node.js,请安装后再试!\nNode.js is not installed, please try again after installation!" >>$LOG_HTM && exit 1
node $JD_SCRIPT >>$LOG_HTM 2>/dev/null && notify &
}
save() {
fill_cookie
add_cron
}
@ -156,7 +136,6 @@ update() {
fi
remote_ver=$(get_ver $TEMP_SCRIPT)
cp -r $TEMP_SCRIPT $JD_SCRIPT
fill_cookie
uci set jd-dailybonus.@global[0].version=$remote_ver
uci commit jd-dailybonus
cancel "0"
@ -169,7 +148,7 @@ while getopts ":alnruswh" arg; do
exit 0
;;
l)
serverchan
notify
exit 0
;;
n)
@ -189,7 +168,7 @@ while getopts ":alnruswh" arg; do
exit 0
;;
w)
back_run
run
exit 0
;;
h)

View File

@ -0,0 +1,303 @@
-- Lua Requests library for http ease
local http_socket = require('socket.http')
local https_socket = require('ssl.https')
local url_parser = require('socket.url')
local ltn12 = require('ltn12')
local json = require('cjson.safe')
local md5sum = require('md5') -- TODO: Make modular?
local mime = require('mime')
local requests = {
_DESCRIPTION = 'Http requests made simpler',
http_socket = http_socket,
https_socket = https_socket
}
local _requests = {}
--User facing function the make a request use Digest Authentication
--TODO: Determine what else should live in authentication
function requests.HTTPDigestAuth(user, password)
return { _type = 'digest', user = user, password = password}
end
--User facing function the make a request use Basic Authentication
--TODO: Determine what else should live in authentication
function requests.HTTPBasicAuth(user, password)
return { _type = 'basic', user = user, password = password}
end
function requests.post(url, args)
return requests.request("POST", url, args)
end
function requests.get(url, args)
return requests.request("GET", url, args)
end
function requests.delete(url, args)
return requests.request("DELETE", url, args)
end
function requests.patch(url, args)
return requests.request("PATCH", url, args)
end
function requests.put(url, args)
return requests.request("PUT", url, args)
end
function requests.options(url, args)
return requests.request("OPTIONS", url, args)
end
function requests.head(url, args)
return requests.request("HEAD", url, args)
end
function requests.trace(url, args)
return requests.request("TRACE", url, args)
end
--Sets up all the data for a request and makes the request
function requests.request(method, url, args)
local request
if type(url) == "table" then
request = url
if not request.url and request[1] then
request.url = table.remove(request, 1)
end
else
request = args or {}
request.url = url
end
request.method = method
_requests.parse_args(request)
-- TODO: Find a better way to do this
if request.auth and request.auth._type == 'digest' then
local response = _requests.make_request(request)
return _requests.use_digest(response, request)
else
return _requests.make_request(request)
end
end
--Makes a request
function _requests.make_request(request)
local response_body = {}
local full_request = {
method = request.method,
url = request.url,
headers = request.headers,
sink = ltn12.sink.table(response_body),
redirect = request.allow_redirects,
proxy = request.proxy
}
if request.data then
full_request.source = ltn12.source.string(request.data)
end
local response = {}
local ok
local socket = string.find(full_request.url, '^https:') and not request.proxy and https_socket or http_socket
ok, response.status_code, response.headers, response.status = socket.request(full_request)
assert(ok, 'error in '..request.method..' request: '..response.status_code)
response.text = table.concat(response_body)
response.json = function () return json.decode(response.text) end
return response
end
--Parses through all the possible arguments for a request
function _requests.parse_args(request)
_requests.check_url(request)
_requests.check_data(request)
_requests.create_header(request)
_requests.check_timeout(request.timeout)
_requests.check_redirect(request.allow_redirects)
end
--Format the the url based on the params argument
function _requests.format_params(url, params) -- TODO: Clean
if not params or next(params) == nil then return url end
url = url..'?'
for key, value in pairs(params) do
if tostring(value) then
url = url..tostring(key)..'='
if type(value) == 'table' then
local val_string = ''
for _, val in ipairs(value) do
val_string = val_string..tostring(val)..','
end
url = url..val_string:sub(0, -2)
else
url = url..tostring(value)
end
url = url..'&'
end
end
return url:sub(0, -2)
end
--Check that there is a URL given and append to it if params are passed in.
function _requests.check_url(request)
assert(request.url, 'No url specified for request')
request.url = _requests.format_params(request.url, request.params)
end
-- Add to the HTTP header
function _requests.create_header(request)
request.headers = request.headers or {}
if request.data then
request.headers['Content-Length'] = request.data:len()
end
if request.cookies then
if request.headers.cookie then
request.headers.cookie = request.headers.cookie..'; '..request.cookies
else
request.headers.cookie = request.cookies
end
end
if request.auth then
_requests.add_auth_headers(request)
end
end
--Makes sure that the data is in a format that can be sent
function _requests.check_data(request)
if type(request.data) == "table" then
request.data = json.encode(request.data)
elseif request.data then
request.data = tostring(request.data)
end
end
--Set the timeout
function _requests.check_timeout(timeout)
http_socket.TIMEOUT = timeout or 5
https_socket.TIMEOUT = timeout or 5
end
--Checks is allow_redirects parameter is set correctly
function _requests.check_redirect(allow_redirects)
if allow_redirects and type(allow_redirects) ~= "boolean" then
error("allow_redirects expects a boolean value. received type = "..type(allow_redirects))
end
end
--Create the Authorization header for Basic Auth
function _requests.basic_auth_header(request)
local encoded = mime.b64(request.auth.user..':'..request.auth.password)
request.headers.Authorization = 'Basic '..encoded
end
-- Create digest authorization string for request header TODO: Could be better, but it should work
function _requests.digest_create_header_string(auth)
local authorization = 'Digest username="'..auth.user..'", realm="'..auth.realm..'", nonce="'..auth.nonce
authorization = authorization..'", uri="'..auth.uri..'", qop='..auth.qop..', nc='..auth.nc
authorization = authorization..', cnonce="'..auth.cnonce..'", response="'..auth.response..'"'
if auth.opaque then
authorization = authorization..', opaque="'..auth.opaque..'"'
end
return authorization
end
--MD5 hash all parameters
local function md5_hash(...)
return md5sum.sumhexa(table.concat({...}, ":"))
end
-- Creates response hash TODO: Add functionality
function _requests.digest_hash_response(auth_table)
return md5_hash(
md5_hash(auth_table.user, auth_table.realm, auth_table.password),
auth_table.nonce,
auth_table.nc,
auth_table.cnonce,
auth_table.qop,
md5_hash(auth_table.method, auth_table.uri)
)
end
-- Add digest authentication to the request header
function _requests.digest_auth_header(request)
if not request.auth.nonce then return end
request.auth.cnonce = request.auth.cnonce or string.format("%08x", os.time())
request.auth.nc_count = request.auth.nc_count or 0
request.auth.nc_count = request.auth.nc_count + 1
request.auth.nc = string.format("%08x", request.auth.nc_count)
local url = url_parser.parse(request.url)
request.auth.uri = url_parser.build{path = url.path, query = url.query}
request.auth.method = request.method
request.auth.qop = 'auth'
request.auth.response = _requests.digest_hash_response(request.auth)
request.headers.Authorization = _requests.digest_create_header_string(request.auth)
end
--Checks the resonse code and adds additional headers for Digest Auth
-- TODO: Rename this
function _requests.use_digest(response, request)
if response.status_code == 401 then
_requests.parse_digest_response_header(response,request)
_requests.create_header(request)
response = _requests.make_request(request)
response.auth = request.auth
response.cookies = request.headers.cookie
return response
else
response.auth = request.auth
response.cookies = request.headers.cookie
return response
end
end
--Parse the first response from the host to make the Authorization header
function _requests.parse_digest_response_header(response, request)
for key, value in response.headers['www-authenticate']:gmatch('(%w+)="(%S+)"') do
request.auth[key] = value
end
if request.headers.cookie then
request.headers.cookie = request.headers.cookie..'; '..response.headers['set-cookie']
else
request.headers.cookie = response.headers['set-cookie']
end
request.auth.nc_count = 0
end
-- Call the correct authentication header function
function _requests.add_auth_headers(request)
local auth_func = {
basic = _requests.basic_auth_header,
digest = _requests.digest_auth_header
}
auth_func[request.auth._type](request)
end
--Return public functions
requests._private = _requests
return requests

View File

@ -36,6 +36,10 @@ s = m:section(NamedSection, sid, "other_rules")
s.anonymous = true
s.addremove = false
o = s:option(Value, "Note", translate("Note"))
o.default = "default"
o.rmempty = false
o = s:option(ListValue, "config", translate("Config File"))
local e,a={}
local groupnames,filename

View File

@ -34,6 +34,7 @@ s:tab("dashboard", translate("Dashboard Settings"))
s:tab("rules_update", translate("Rules Update"))
s:tab("geo_update", translate("GEOIP Update"))
s:tab("chnr_update", translate("Chnroute Update"))
s:tab("auto_restart", translate("Auto Restart"))
s:tab("version_update", translate("Version Update"))
s:tab("debug", translate("Debug Logs"))
@ -469,6 +470,27 @@ o.write = function()
end
end
o = s:taboption("auto_restart", Flag, "auto_restart", translate("Auto Restart"))
o.description = translate("Auto Restart OpenClash")
o.default=0
o = s:taboption("auto_restart", ListValue, "auto_restart_week_time", translate("Restart Time (Every Week)"))
o:value("*", translate("Every Day"))
o:value("1", translate("Every Monday"))
o:value("2", translate("Every Tuesday"))
o:value("3", translate("Every Wednesday"))
o:value("4", translate("Every Thursday"))
o:value("5", translate("Every Friday"))
o:value("6", translate("Every Saturday"))
o:value("0", translate("Every Sunday"))
o.default=1
o = s:taboption("auto_restart", ListValue, "auto_restart_day_time", translate("Restart time (every day)"))
for t = 0,23 do
o:value(t, t..":00")
end
o.default=0
---- Dashboard Settings
local lan_ip=SYS.exec("uci get network.lan.ipaddr 2>/dev/null |awk -F '/' '{print $1}' 2>/dev/null |tr -d '\n'")
local cn_port=SYS.exec("uci get openclash.config.cn_port 2>/dev/null |tr -d '\n'")
@ -593,6 +615,11 @@ function o.cfgvalue(...)
end
end
o = ss:option(DummyValue, "Note", translate("Note"))
function o.cfgvalue(...)
return Value.cfgvalue(...) or translate("None")
end
-- [[ Edit Authentication ]] --
s = m:section(TypedSection, "authentication", translate("Set Authentication of SOCKS5/HTTP(S)"))
s.anonymous = true

View File

@ -1424,3 +1424,18 @@ msgstr "选择配置文件后请点击以获取对应的策略组"
msgid "Other Rules Name"
msgstr "第三方规则"
msgid "Note"
msgstr "备注"
msgid "Auto Restart"
msgstr "定时重启"
msgid "Auto Restart OpenClash"
msgstr "定时重启插件"
msgid "Restart Time (Every Week)"
msgstr "重启时间(每周)"
msgid "Restart time (every day)"
msgstr "重启时间(每天)"

View File

@ -48,6 +48,9 @@ add_cron()
[ -z "$(grep "openclash_chnroute.sh" "$CRON_FILE" 2>/dev/null)" ] && {
[ "$(uci get openclash.config.chnr_auto_update 2>/dev/null)" -eq 1 ] && echo "0 $(uci get openclash.config.chnr_update_day_time 2>/dev/null) * * $(uci get openclash.config.chnr_update_week_time 2>/dev/null) /usr/share/openclash/openclash_chnroute.sh" >> $CRON_FILE
}
[ -z "$(grep "/etc/init.d/openclash" "$CRON_FILE" 2>/dev/null)" ] && {
[ "$(uci get openclash.config.auto_restart 2>/dev/null)" -eq 1 ] && echo "0 $(uci get openclash.config.auto_restart_day_time 2>/dev/null) * * $(uci get openclash.config.auto_restart_week_time 2>/dev/null) /etc/init.d/openclash restart 2>/dev/null" >> $CRON_FILE
}
crontab $CRON_FILE
nohup /usr/share/openclash/openclash_watchdog.sh &
}
@ -1291,11 +1294,13 @@ fi
fi
#common ports
common_port="21 22 23 53 80 123 143 194 443 465 587 853 993 995 998 2052 2053 2082 2083 2086 2095 2096 5222 5228 5229 5230 8080 8443 8880 8888 8889"
ipset create common_ports bitmap:port range 0-65535
for i in $common_port; do
ipset add common_ports $i
done
if [ "$common_ports" = "1" ]; then
common_port="21 22 23 53 80 123 143 194 443 465 587 853 993 995 998 2052 2053 2082 2083 2086 2095 2096 5222 5228 5229 5230 8080 8443 8880 8888 8889"
ipset create common_ports bitmap:port range 0-65535
for i in $common_port; do
ipset add common_ports $i
done
fi
if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 3 ]; then
#tcp
@ -1308,9 +1313,7 @@ if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 3 ]; then
iptables -t nat -A openclash -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
iptables -t nat -A openclash -m set ! --match-set lan_ac_white_ips src -j RETURN >/dev/null 2>&1
if [ "$en_mode" = "redir-host" ]; then
if [ "$common_ports" = "1" ]; then
iptables -t nat -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
fi
iptables -t nat -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
iptables -t nat -A openclash -m set --match-set china_ip_route dst -j RETURN >/dev/null 2>&1
fi
iptables -t nat -A openclash -p tcp -j REDIRECT --to-ports "$proxy_port"
@ -1333,9 +1336,7 @@ if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 3 ]; then
iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_ips src -j RETURN >/dev/null 2>&1
iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
if [ "$en_mode" = "redir-host" ]; then
if [ "$common_ports" = "1" ]; then
iptables -t mangle -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
fi
iptables -t mangle -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
iptables -t mangle -A openclash -m set --match-set china_ip_route dst -j RETURN >/dev/null 2>&1
fi
iptables -t mangle -A openclash -p udp --dport 53 -j RETURN >/dev/null 2>&1
@ -1444,9 +1445,7 @@ if [ -n "$en_mode_tun" ]; then
iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_ips src -j RETURN >/dev/null 2>&1
iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
if [ "$en_mode" = "redir-host" ]; then
if [ "$common_ports" = "1" ]; then
iptables -t mangle -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
fi
iptables -t mangle -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
iptables -t mangle -A openclash -m set --match-set china_ip_route dst -j RETURN >/dev/null 2>&1
fi
iptables -t mangle -A openclash -j MARK --set-mark "$PROXY_FWMARK"

View File

@ -48,7 +48,7 @@ yml_other_rules_del()
if [ "$enabled" = "0" ] || [ "$config" != "$2" ] || [ "$rule_name" != "$3" ]; then
return
else
uci delete openclash."$section" 2>/dev/null
uci set openclash."$section".enabled=0 2>/dev/null
fi
}
#写入代理集到配置文件

View File

@ -1,8 +1,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-vssr
PKG_VERSION:=1.21
PKG_RELEASE:=20210114
PKG_VERSION:=1.22
PKG_RELEASE:=20210119
include $(INCLUDE_DIR)/package.mk
@ -46,7 +46,7 @@ define Package/luci-app-vssr
SUBMENU:=3. Applications
TITLE:=A New SS/SSR/V2Ray/Trojan LuCI interface
PKGARCH:=all
DEPENDS:=+shadowsocksr-libev-alt +ipset +ip-full +iptables-mod-tproxy +dnsmasq-full +coreutils +coreutils-base64 +bash +pdnsd-alt +wget-ssl +luasocket +lua-maxminddb \
DEPENDS:=+shadowsocksr-libev-alt +ipset +ip-full +iptables-mod-tproxy +dnsmasq-full +coreutils +coreutils-base64 +bash +pdnsd-alt +wget-ssl +lua +luasocket +lua-maxminddb \
+shadowsocks-libev-ss-local +shadowsocksr-libev-ssr-local +shadowsocks-libev-ss-redir +simple-obfs \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_plugin:v2ray-plugin \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray \

View File

@ -12,12 +12,13 @@ function index()
entry({'admin', 'services', 'vssr', 'client'}, cbi('vssr/client'), _('SSR Client'), 10).leaf = true -- 基本设置
entry({'admin', 'services', 'vssr', 'servers'}, cbi('vssr/servers'), _('Severs Nodes'), 11).leaf = true -- 服务器节点
entry({'admin', 'services', 'vssr', 'servers'}, arcombine(cbi('vssr/servers'), cbi('vssr/client-config')), _('Severs Nodes'), 11).leaf = true -- 编辑节点
entry({'admin', 'services', 'vssr', 'control'}, cbi('vssr/control'), _('Access Control'), 12).leaf = true -- 访问控制
entry({'admin', 'services', 'vssr', 'router'}, cbi('vssr/router'), _('Router Config'), 13).leaf = true -- 访问控制
entry({'admin', 'services', 'vssr', 'subscribe_config'}, cbi('vssr/subscribe-config', {hideapplybtn = true, hidesavebtn = true, hideresetbtn = true}), _('Subscribe'), 12).leaf = true -- 订阅设置
entry({'admin', 'services', 'vssr', 'control'}, cbi('vssr/control'), _('Access Control'), 13).leaf = true -- 访问控制
entry({'admin', 'services', 'vssr', 'router'}, cbi('vssr/router'), _('Router Config'), 14).leaf = true -- 访问控制
if nixio.fs.access('/usr/bin/v2ray/v2ray') or nixio.fs.access('/usr/bin/v2ray') or nixio.fs.access('/usr/bin/xray') or nixio.fs.access('/usr/bin/xray/xray') then
entry({'admin', 'services', 'vssr', 'socks5'}, cbi('vssr/socks5'), _('Socks5'), 14).leaf = true -- Socks5代理
entry({'admin', 'services', 'vssr', 'socks5'}, cbi('vssr/socks5'), _('Local Proxy'), 15).leaf = true -- Socks5代理
end
entry({'admin', 'services', 'vssr', 'advanced'}, cbi('vssr/advanced'), _('Advanced Settings'), 15).leaf = true -- 高级设置
entry({'admin', 'services', 'vssr', 'advanced'}, cbi('vssr/advanced'), _('Advanced Settings'), 16).leaf = true -- 高级设置
elseif nixio.fs.access('/usr/bin/ssr-server') then
entry({'admin', 'services', 'vssr'}, alias('admin', 'services', 'vssr', 'server'), _('vssr'), 10).dependent = true
else
@ -240,11 +241,7 @@ function refresh_data()
local icount = 0
if set == 'gfw_data' then
if nixio.fs.access('/usr/bin/wget-ssl') then
refresh_cmd = 'wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O /tmp/gfw.b64'
else
refresh_cmd = 'wget -O /tmp/gfw.b64 http://iytc.net/tools/list.b64'
end
refresh_cmd = 'wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O /tmp/gfw.b64'
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
if sret == 0 then
luci.sys.call('/usr/bin/vssr-gfw')
@ -265,7 +262,7 @@ function refresh_data()
retstring = '-1'
end
elseif set == 'ip_data' then
refresh_cmd ="wget -O- 'https://ispip.clang.cn/all_cn.txt' > /tmp/china_ssr.txt 2>/dev/null"
refresh_cmd = "wget-ssl -O- 'https://ispip.clang.cn/all_cn.txt' > /tmp/china_ssr.txt 2>/dev/null"
sret = luci.sys.call(refresh_cmd)
icount = luci.sys.exec('cat /tmp/china_ssr.txt | wc -l')
if sret == 0 and tonumber(icount) > 1000 then
@ -282,12 +279,8 @@ function refresh_data()
luci.sys.exec('rm -f /tmp/china_ssr.txt ')
else
local need_process = 0
if nixio.fs.access('/usr/bin/wget-ssl') then
refresh_cmd = 'wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf'
need_process = 1
else
refresh_cmd = 'wget -O /tmp/ad.conf http://iytc.net/tools/ad.conf'
end
refresh_cmd = 'wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf'
need_process = 1
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
if sret == 0 then
if need_process == 1 then
@ -319,4 +312,4 @@ function refresh_data()
end
luci.http.prepare_content('application/json')
luci.http.write_json({ret = retstring, retcount = icount})
end
end

View File

@ -61,59 +61,6 @@ o.datatype = 'uinteger'
o:depends('enable_switch', '1')
o.default = 3
-- [[ 节点订阅 ]]--
s = m:section(TypedSection, 'server_subscribe', translate('Servers subscription and manage'))
s.anonymous = true
o = s:option(Flag, 'auto_update', translate('Auto Update'))
o.rmempty = false
o.description = translate('Auto Update Server subscription, GFW list and CHN route')
o = s:option(ListValue, 'auto_update_time', translate('Update time (every day)'))
for t = 0, 23 do
o:value(t, t .. ':00')
end
o.default = 2
o.rmempty = false
o = s:option(DynamicList, 'subscribe_url', translate('Subscribe URL'))
o.rmempty = true
o.description = translate('You can manually add group names in front of the URL, splited by ,')
o = s:option(Value, "filter_words", translate("Subscribe Filter Words"))
o.rmempty = true
o.description = translate("Filter Words splited by /")
o = s:option(Flag, 'proxy', translate('Through proxy update'))
o.rmempty = false
o.description = translate('Through proxy update list, Not Recommended ')
o = s:option(DummyValue, '', '')
o.rawhtml = true
o.template = 'vssr/update_subscribe'
o = s:option(Button, 'delete', translate('Delete All Subscribe Severs'))
o.inputstyle = 'reset'
o.description = string.format(translate('Server Count') .. ': %d', server_count)
o.write = function()
uci:delete_all(
'vssr',
'servers',
function(s)
if s.hashkey or s.isSubscribe then
return true
else
return false
end
end
)
uci:save('vssr')
uci:commit('vssr')
luci.sys.exec('/etc/init.d/vssr restart')
luci.http.redirect(luci.dispatcher.build_url('admin', 'services', 'vssr', 'servers'))
return
end
-- [[ adblock ]]--
s = m:section(TypedSection, 'global', translate('adblock settings'))

View File

@ -93,15 +93,7 @@ for i, v in pairs(route_name) do
o = s:option(ListValue, v, translate(route_label[i]))
o:value('nil', translate('Same as Main Server'))
for _, key in pairs(server_table) do
if(v == 'tw_video_server' and key.flag == "tw") then
o:value(key.name, key.gname)
end
if(v == 'tvb_server' and key.flag == "hk") then
o:value(key.name, key.gname)
end
if(v ~= 'tvb_server' and v ~= 'tw_video_server') then
o:value(key.name, key.gname)
end
o:value(key.name, key.gname)
end
o:depends('v2ray_flow', '1')
o.default = 'nil'

View File

@ -2,7 +2,8 @@ local fs = require 'nixio.fs'
local conffile = '/tmp/ssrpro.log'
f = SimpleForm('logview')
f.submit = false
f.reset = false
t = f:field(TextValue, 'conf')
t.rmempty = true
t.rows = 20

View File

@ -1,31 +1,31 @@
local m, s, o
local NXFS = require 'nixio.fs'
local router_table = {
yotube = {
a1 = {
name = 'youtube',
des = 'Youtube Domain'
},
tw_video = {
a2 = {
name = 'tw_video',
des = 'Tw Video Domain'
},
netflix = {
a3 = {
name = 'netflix',
des = 'Netflix Domain'
},
disney = {
a4 = {
name = 'disney',
des = 'Disney+ Domain'
},
prime = {
a5 = {
name = 'prime',
des = 'Prime Video Domain'
},
tvb = {
a6 = {
name = 'tvb',
des = 'TVB Domain'
},
custom = {
a7 = {
name = 'custom',
des = 'Custom Domain'
}
@ -39,6 +39,7 @@ for _, v in pairs(router_table) do
local conf = '/etc/vssr/'.. v.name ..'_domain.list'
o = s:taboption(v.name, TextValue, v.name ..'conf')
o.rows = 13
o.description = translate('↑ Put your domain list here')
o.wrap = 'off'
o.rmempty = true
o.cfgvalue = function(self, section)
@ -50,6 +51,23 @@ for _, v in pairs(router_table) do
o.remove = function(self, section, value)
NXFS.writefile(conf, '')
end
local conf1 = '/etc/vssr/'.. v.name ..'_ip.list'
o = s:taboption(v.name, TextValue, v.name ..'conf1')
o.rows = 13
o.wrap = 'off'
o.description = translate('↑ Put your IP list here')
o.rmempty = true
o.cfgvalue = function(self, section)
return NXFS.readfile(conf1) or ' '
end
o.write = function(self, section, value)
NXFS.writefile(conf1, value:gsub('\r\n', '\n'))
end
o.remove = function(self, section, value)
NXFS.writefile(conf1, '')
end
end
return m

View File

@ -0,0 +1,77 @@
local vssr = 'vssr'
local uci = luci.model.uci.cursor()
local server_table = {}
local gfwmode = 0
local gfw_count = 0
local ip_count = 0
local ad_count = 0
local server_count = 0
local sys = require 'luci.sys'
uci:foreach(
'vssr',
'servers',
function(s)
server_count = server_count + 1
end
)
m = Map(vssr)
-- [[ 节点订阅 ]]--
s = m:section(TypedSection, 'server_subscribe', translate('Servers subscription and manage'))
s.anonymous = true
o = s:option(Flag, 'auto_update', translate('Auto Update'))
o.rmempty = false
o.description = translate('Auto Update Server subscription, GFW list and CHN route')
o = s:option(ListValue, 'auto_update_time', translate('Update time (every day)'))
for t = 0, 23 do
o:value(t, t .. ':00')
end
o.default = 2
o.rmempty = false
o = s:option(DynamicList, 'subscribe_url', translate('Subscribe URL'))
o.rmempty = true
o.description = translate('You can manually add group names in front of the URL, splited by ,')
o = s:option(Value, 'filter_words', translate('Subscribe Filter Words'))
o.rmempty = true
o.description = translate('Filter Words splited by /')
o = s:option(Flag, 'proxy', translate('Through proxy update'))
o.rmempty = false
o.description = translate('Through proxy update list, Not Recommended ')
o = s:option(DummyValue, '', '')
o.rawhtml = true
o.template = 'vssr/update_subscribe'
o = s:option(Button, 'delete', translate('Delete All Subscribe Severs'))
o.inputstyle = 'reset'
o.description = string.format(translate('Server Count') .. ': %d', server_count)
o.write = function()
uci:delete_all(
'vssr',
'servers',
function(s)
if s.hashkey or s.isSubscribe then
return true
else
return false
end
end
)
uci:save('vssr')
uci:commit('vssr')
luci.sys.exec('/etc/init.d/vssr restart')
luci.http.redirect(luci.dispatcher.build_url('admin', 'services', 'vssr', 'servers'))
return
end
return m

View File

@ -2,304 +2,305 @@
<script type="text/javascript">//<![CDATA[
const GET_FLAG_URL = '<%=luci.dispatcher.build_url("admin", "services", "vssr","flag")%>';
var sid;
const GET_FLAG_URL = '<%=luci.dispatcher.build_url("admin", "services", "vssr","flag")%>';
var sid;
function getFlag(remark, hosts, sid) {
XHR.get(GET_FLAG_URL,
{ host: hosts, remark: remark },
function (x, rv) {
el('.flag').value = rv.flag.replace(/[\r\n]/g, "");
function getFlag(remark, hosts, sid) {
XHR.get(GET_FLAG_URL,
{ host: hosts, remark: remark },
function (x, rv) {
el('.flag').value = rv.flag.replace(/[\r\n]/g, "");
}
);
}
function padright(str, cnt, pad) {
return str + Array(cnt + 1).join(pad);
}
function b64EncodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
function b64encutf8safe(str) {
return b64EncodeUnicode(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '');
}
function b64DecodeUnicode(str) {
return decodeURIComponent(Array.prototype.map.call(atob(str), function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
}
function b64decutf8safe(str) {
var l;
str = str.replace(/-/g, "+").replace(/_/g, "/");
l = str.length;
l = (4 - l % 4) % 4;
if (l)
str = padright(str, l, "=");
return b64DecodeUnicode(str);
}
function b64encsafe(str) {
return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '')
}
function b64decsafe(str) {
var l;
str = str.replace(/-/g, "+").replace(/_/g, "/");
l = str.length;
l = (4 - l % 4) % 4;
if (l)
str = padright(str, l, "=");
try {
return atob(str);
} catch (err) {
return str;
}
);
}
function padright(str, cnt, pad) {
return str + Array(cnt + 1).join(pad);
}
function b64EncodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
function b64encutf8safe(str) {
return b64EncodeUnicode(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '');
}
function b64DecodeUnicode(str) {
return decodeURIComponent(Array.prototype.map.call(atob(str), function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
}
function b64decutf8safe(str) {
var l;
str = str.replace(/-/g, "+").replace(/_/g, "/");
l = str.length;
l = (4 - l % 4) % 4;
if (l)
str = padright(str, l, "=");
return b64DecodeUnicode(str);
}
function b64encsafe(str) {
return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '')
}
function b64decsafe(str) {
var l;
str = str.replace(/-/g, "+").replace(/_/g, "/");
l = str.length;
l = (4 - l % 4) % 4;
if (l)
str = padright(str, l, "=");
try {
return atob(str);
} catch (err) {
return str;
}
}
function dictvalue(d, key) {
var v = d[key];
if (typeof (v) == 'undefined' || v == '')
return '';
return b64decsafe(v);
}
function el(id) {
return document.getElementById('cbid.vssr.' + sid + id);
}
function import_ssr_url(btn, urlname, sids) {
sid = sids;
var s = document.getElementById(urlname + '-status');
if (!s)
return false;
var ssrurl = prompt("<%:Paste Node Link Here%> ssr:// | ss:// | vmess:// | trojan://", "");
if (ssrurl == null || ssrurl == "") {
s.innerHTML = "<font color='red'><%:User Cancel%></font>";
return false;
}
s.innerHTML = "";
//var ssu = ssrurl.match(/ssr:\/\/([A-Za-z0-9_-]+)/i);
var ssu = ssrurl.split('://');
console.log(ssu.length);
if ((ssu[0] != "ssr" && ssu[0] != "ss" && ssu[0] != "vmess" && ssu[0] != "trojan") || ssu[1] == "") {
s.innerHTML = "<font color='red'><%:Invalid Format%></font>";
return false;
function dictvalue(d, key) {
var v = d[key];
if (typeof (v) == 'undefined' || v == '')
return '';
return b64decsafe(v);
}
function el(id) {
return document.getElementById('cbid.vssr.' + sid + id);
}
var event = document.createEvent("HTMLEvents");
event.initEvent("change", true, true);
var rema = "";
if (ssu[0] == "ssr") {
var sstr = b64decsafe(ssu[1]);
var ploc = sstr.indexOf("/?");
el('.type').value = "ssr";
el('.type').dispatchEvent(event);
var url0, param = "";
if (ploc > 0) {
url0 = sstr.substr(0, ploc);
param = sstr.substr(ploc + 2);
}
var ssm = url0.match(/^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)/);
if (!ssm || ssm.length < 7)
function import_ssr_url(btn, urlname, sids) {
sid = sids;
var s = document.getElementById(urlname + '-status');
if (!s)
return false;
var ssrurl = prompt("<%:Paste Node Link Here%> ssr:// | ss:// | vmess:// | trojan://", "");
if (ssrurl == null || ssrurl == "") {
s.innerHTML = "<font color='red'><%:User Cancel%></font>";
return false;
var pdict = {};
if (param.length > 2) {
var a = param.split('&');
for (var i = 0; i < a.length; i++) {
var b = a[i].split('=');
pdict[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '');
}
}
el('.server').value = ssm[1];
el('.server_port').value = ssm[2];
el('.protocol').value = ssm[3];
el('.encrypt_method').value = ssm[4];
el('.obfs').value = ssm[5];
el('.password').value = b64decsafe(ssm[6]);
el('.obfs_param').value = dictvalue(pdict, 'obfsparam');
el('.protocol_param').value = dictvalue(pdict, 'protoparam');
s.innerHTML = "";
//var ssu = ssrurl.match(/ssr:\/\/([A-Za-z0-9_-]+)/i);
var ssu = ssrurl.split('://');
console.log(ssu.length);
var rem = pdict['remarks'];
if (typeof (rem) != 'undefined' && rem != '' && rem.length > 0)
rema = b64decutf8safe(rem);
el('.alias').value = b64decutf8safe(rem);
getFlag(rema, ssm[1], sid); //get flag iso code
s.innerHTML = "<font color='green'><%:Import%>ShadowsocksR<%:Configuration Succeeded%></font>";
return false;
} else if (ssu[0] == "ss") {
var url0, param = "";
var sipIndex = ssu[1].indexOf("@");
var ploc = ssu[1].indexOf("#");
if (ploc > 0) {
url0 = ssu[1].substr(0, ploc);
param = ssu[1].substr(ploc + 1);
} else {
url0 = ssu[1];
}
var event = document.createEvent("HTMLEvents");
event.initEvent("change", true, true);
var rema = "";
switch (ssu[0]) {
case "ssr":
var sstr = b64decsafe(ssu[1]);
var ploc = sstr.indexOf("/?");
el('.type').value = "ssr";
el('.type').dispatchEvent(event);
var url0, param = "";
if (ploc > 0) {
url0 = sstr.substr(0, ploc);
param = sstr.substr(ploc + 2);
}
var ssm = url0.match(/^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)/);
if (!ssm || ssm.length < 7)
return false;
var pdict = {};
if (param.length > 2) {
var a = param.split('&');
for (var i = 0; i < a.length; i++) {
var b = a[i].split('=');
pdict[decodeURIComponent(b[0])] = decodeURIComponent(b[1] || '');
}
}
el('.server').value = ssm[1];
el('.server_port').value = ssm[2];
el('.protocol').value = ssm[3];
el('.encrypt_method').value = ssm[4];
el('.obfs').value = ssm[5];
el('.password').value = b64decsafe(ssm[6]);
el('.obfs_param').value = dictvalue(pdict, 'obfsparam');
el('.protocol_param').value = dictvalue(pdict, 'protoparam');
if (sipIndex != -1) {
// SIP002
var userInfo = b64decsafe(url0.substr(0, sipIndex));
var temp = url0.substr(sipIndex + 1).split("/?");
var serverInfo = temp[0].split(":");
var server = serverInfo[0];
var port = serverInfo[1];
var method, password, plugin, pluginOpts;
if (temp[1]) {
var pluginInfo = decodeURIComponent(temp[1]);
var pluginIndex = pluginInfo.indexOf(";");
var pluginNameInfo = pluginInfo.substr(0, pluginIndex);
plugin = pluginNameInfo.substr(pluginNameInfo.indexOf("=") + 1)
pluginOpts = pluginInfo.substr(pluginIndex + 1);
}
var rem = pdict['remarks'];
if (typeof (rem) != 'undefined' && rem != '' && rem.length > 0)
rema = b64decutf8safe(rem);
el('.alias').value = b64decutf8safe(rem);
getFlag(rema, ssm[1], sid); //get flag iso code
s.innerHTML = "<font color='green'><%:Import%>ShadowsocksR<%:Configuration Succeeded%></font>";
break;
case "ss":
var url0, param = "";
var sipIndex = ssu[1].indexOf("@");
var ploc = ssu[1].indexOf("#");
if (ploc > 0) {
url0 = ssu[1].substr(0, ploc);
param = ssu[1].substr(ploc + 1);
} else {
url0 = ssu[1];
}
var userInfoSplitIndex = userInfo.indexOf(":");
if (userInfoSplitIndex != -1) {
method = userInfo.substr(0, userInfoSplitIndex);
password = userInfo.substr(userInfoSplitIndex + 1);
}
el('.type').value = "ss";
el('.type').dispatchEvent(event);
el('.server').value = server;
el('.server_port').value = port;
el('.password').value = password || "";
el('.encrypt_method_ss').value = method || "";
el('.plugin').value = plugin || "";
el('.plugin_opts').value = pluginOpts || "";
} else {
var sstr = b64decsafe(url0);
el('.type').value = "ss";
el('.type').dispatchEvent(event);
var team = sstr.split('@');
console.log(param);
var part1 = team[0].split(':');
var part2 = team[1].split(':');
el('.server').value = part2[0];
el('.server_port').value = part2[1];
el('.password').value = part1[1];
el('.encrypt_method_ss').value = part1[0];
el('.plugin').value = "";
el('.plugin_opts').value = "";
}
if (sipIndex != -1) {
// SIP002
var userInfo = b64decsafe(url0.substr(0, sipIndex));
var temp = url0.substr(sipIndex + 1).split("/?");
if(temp.length == 1){
temp = url0.substr(sipIndex + 1).split("?");
}
var serverInfo = temp[0].split(":");
var server = serverInfo[0];
var port = serverInfo[1];
var method, password, plugin, pluginOpts;
if (temp[1]) {
var pluginInfo = decodeURIComponent(temp[1]);
var pluginIndex = pluginInfo.indexOf(";");
var pluginNameInfo = pluginInfo.substr(0, pluginIndex);
plugin = pluginNameInfo.substr(pluginNameInfo.indexOf("=") + 1)
pluginOpts = pluginInfo.substr(pluginIndex + 1);
}
if (param != undefined) {
rema = decodeURI(param)
el('.alias').value = decodeURI(param);
}
getFlag(rema, server, sid); //get flag iso code
s.innerHTML = "<font color='green'><%:Import%>Shadowsocks<%:Configuration Succeeded%></font>";
return false;
} else if (ssu[0] == "trojan") {
var ploc = ssu[1].indexOf("#");
if (ploc > 0) {
url0 = ssu[1].substr(0, ploc);
param = ssu[1].substr(ploc + 1);
} else {
url0 = ssu[1]
}
var sstr = b64decsafe(url0);
el('.type').value = "trojan";
el('.type').dispatchEvent(event);
var team = sstr.split('@');
console.log(team);
var part1 = team[0].split(':');
var part2 = team[1].split(':');
var others = part2[1].split('?');
var queryParam = {}
if (others.length > 1) {
var queryParams = others[1]
var queryArray = queryParams.split('&')
for (i = 0; i < queryArray.length; i++) {
var params = queryArray[i].split('=');
queryParam[decodeURIComponent(params[0])] = decodeURIComponent(params[1] || '');
}
}
el('.server').value = part2[0];
el('.server_port').value = others[0];
el('.password').value = part1[0];
if (queryParam.peer || queryParam.sni) {
el('.tls').checked = true;
el('.peer').value = queryParam.peer || queryParam.sni;
}
var userInfoSplitIndex = userInfo.indexOf(":");
if (userInfoSplitIndex != -1) {
method = userInfo.substr(0, userInfoSplitIndex);
password = userInfo.substr(userInfoSplitIndex + 1);
}
el('.type').value = "ss";
el('.type').dispatchEvent(event);
el('.server').value = server;
el('.server_port').value = port;
el('.password').value = password || "";
el('.encrypt_method_ss').value = method || "";
el('.plugin').value = plugin || "";
el('.plugin_opts').value = pluginOpts || "";
} else {
var sstr = b64decsafe(url0);
el('.type').value = "ss";
el('.type').dispatchEvent(event);
var team = sstr.split('@');
console.log(param);
var part1 = team[0].split(':');
var part2 = team[1].split(':');
el('.server').value = part2[0];
el('.server_port').value = part2[1];
el('.password').value = part1[1];
el('.encrypt_method_ss').value = part1[0];
el('.plugin').value = "";
el('.plugin_opts').value = "";
}
if (param != undefined) {
rema = decodeURI(param)
el('.alias').value = decodeURI(param);
}
getFlag(rema, part2[0], sid); //get flag iso code
if (param != undefined) {
rema = decodeURI(param)
el('.alias').value = decodeURI(param);
}
getFlag(rema, server, sid); //get flag iso code
s.innerHTML = "<font color='green'><%:Import%>Shadowsocks<%:Configuration Succeeded%></font>";
break;
case "trojan":
var ploc = ssu[1].indexOf("#");
if (ploc > 0) {
url0 = ssu[1].substr(0, ploc);
param = ssu[1].substr(ploc + 1);
} else {
url0 = ssu[1]
}
var sstr = b64decsafe(url0);
el('.type').value = "trojan";
el('.type').dispatchEvent(event);
var team = sstr.split('@');
console.log(team);
var part1 = team[0].split(':');
var part2 = team[1].split(':');
var others = part2[1].split('?');
var queryParam = {}
if (others.length > 1) {
var queryParams = others[1]
var queryArray = queryParams.split('&')
for (i = 0; i < queryArray.length; i++) {
var params = queryArray[i].split('=');
queryParam[decodeURIComponent(params[0])] = decodeURIComponent(params[1] || '');
}
}
el('.server').value = part2[0];
el('.server_port').value = others[0];
el('.password').value = part1[0];
if (queryParam.peer || queryParam.sni) {
el('.tls').checked = true;
el('.peer').value = queryParam.peer || queryParam.sni;
}
s.innerHTML = "<font color='green'>导入Trojan<%:Configuration Succeeded%></font>";
return false;
} else if (ssu[0] == "vmess") {
var sstr = b64DecodeUnicode(ssu[1]);
var ploc = sstr.indexOf("/?");
el('.type').value = "v2ray";
el('.type').dispatchEvent(event);
var url0, param = "";
if (ploc > 0) {
url0 = sstr.substr(0, ploc);
param = sstr.substr(ploc + 2);
}
var ssm = JSON.parse(sstr);
el('.alias').value = ssm.ps;
el('.server').value = ssm.add;
el('.server_port').value = ssm.port;
el('.alter_id').value = ssm.aid;
el('.vmess_id').value = ssm.id;
el('.transport').value = ssm.net;
el('.transport').dispatchEvent(event);
if (ssm.net == "tcp") {
try {
el('.http_host').value = ssm.host;
el('.http_path').value = ssm.path;
} catch (err) { }
if (param != undefined) {
rema = decodeURI(param)
el('.alias').value = decodeURI(param);
}
getFlag(rema, part2[0], sid); //get flag iso code
s.innerHTML = "<font color='green'>导入Trojan<%:Configuration Succeeded%></font>";
break;
case "vmess":
var sstr = b64DecodeUnicode(ssu[1]);
var ploc = sstr.indexOf("/?");
el('.type').value = "v2ray";
el('.type').dispatchEvent(event);
var url0, param = "";
if (ploc > 0) {
url0 = sstr.substr(0, ploc);
param = sstr.substr(ploc + 2);
}
var ssm = JSON.parse(sstr);
el('.alias').value = ssm.ps;
el('.server').value = ssm.add;
el('.server_port').value = ssm.port;
el('.alter_id').value = ssm.aid;
el('.vmess_id').value = ssm.id;
el('.transport').value = ssm.net;
el('.transport').dispatchEvent(event);
if (ssm.net == "tcp") {
try {
el('.http_host').value = ssm.host;
el('.http_path').value = ssm.path;
} catch (err) { }
}
if (ssm.net == "ws") {
try {
el('.ws_host').value = ssm.host;
el('.ws_path').value = ssm.path;
} catch (err) { }
}
if (ssm.net == "h2") {
try {
el('.h2_host').value = ssm.host;
el('.h2_path').value = ssm.path;
} catch (err) { }
}
if (ssm.net == "quic") {
try {
el('.quic_security').value = ssm.securty;
el('.quic_key').value = ssm.key;
} catch (err) { }
}
if (ssm.net == "kcp") {
try {
el('.kcp_guise').value = ssm.type;
} catch (err) { }
try {
el('.seed').value = ssm.seed;
} catch (err) { }
}
if (ssm.tls == "tls") {
try {
el('.tls').checked = true;
el('.tls').dispatchEvent(event);
el('.tls_host').value = ssm.host;
} catch (err) { }
}
el('.mux').checked = true;
el('.mux').dispatchEvent(event);
getFlag(ssm.ps, ssm.add, sid); //get flag iso code
s.innerHTML = "<font color='green'><%:Import%>V2ray<%:Configuration Succeeded%></font>";
break;
default:
s.innerHTML = "<font color='red'><%:Invalid Format%></font>";
}
if (ssm.net == "ws") {
try {
el('.ws_host').value = ssm.host;
el('.ws_path').value = ssm.path;
} catch (err) { }
}
if (ssm.net == "h2") {
try {
el('.h2_host').value = ssm.host;
el('.h2_path').value = ssm.path;
} catch (err) { }
}
if (ssm.net == "quic") {
try {
el('.quic_security').value = ssm.securty;
el('.quic_key').value = ssm.key;
} catch (err) { }
}
if (ssm.net == "kcp") {
try {
el('.kcp_guise').value = ssm.type;
} catch (err) { }
try {
el('.seed').value = ssm.seed;
} catch (err) { }
}
if (ssm.tls == "tls") {
try {
el('.tls').checked = true;
el('.tls').dispatchEvent(event);
el('.tls_host').value = ssm.host;
} catch (err) { }
}
el('.mux').checked = true;
el('.mux').dispatchEvent(event);
getFlag(ssm.ps, ssm.add, sid); //get flag iso code
s.innerHTML = "<font color='green'><%:Import%>V2ray<%:Configuration Succeeded%></font>";
return false;
}
}
//]]></script>
<input type="button" class="cbi-button cbi-button-apply" value="<%:Import Configuration%>"

View File

@ -26,6 +26,9 @@
function resize() {
wW = $(window).width();
lw = $(".main-left").width()
if(lw == undefined){
lw = 0;
}
$(".status-bar").width(wW - lw);
$(".status-bar .flag").width($(".status-bar .flag").height() / 3 * 4);

View File

@ -1,6 +1,6 @@
<% math.randomseed(os.time()) %>
<link rel="stylesheet" href="/luci-static/vssr/css/vssr.css?v=<%=math.random(1,100000)%>">
<script src="<%=media%>/js/jquery.min.js"></script>
<script src="/luci-static/vssr/jquery.min.js"></script>
<div class="pure-g status">
<div class="pure-u-1-4">

View File

@ -3,87 +3,113 @@
<script type="text/javascript" src="/luci-static/vssr/polyfill.js?v=1.16"></script>
<!-- tblsection -->
<fieldset class="cbi-section" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
<button class="cbi-button cbi-button-check "><%:Ping All Servers%></button><span class="panel-title">总计
<%- print(self.des)-%>个节点</span>
<div class="ssr-title">
<button class="cbi-button cbi-button-check ">
<%:Ping All Servers%>
</button><span class="panel-title">总计
<%- print(self.des)-%>个节点
</span>
<div style="clear:both;"></div>
</div>
<div class="cbi-section-node">
<%- local count = 0 -%>
<div class="cbi-section-table pure-g p-in5">
<%- local count=0 -%>
<div class="cbi-section-table pure-g p-in5">
<%- local isempty=true for i, k in ipairs(self.serverTable) do section=k isempty=false local
fc=(section.name==self.current) and "fast" or "" local flag_icon=(section.flag ~=nil)
and "flag-icon-" .. section.flag or "flag-icon-un" local switch_enable=(section.switch_enable=="1" )
and "" or "hidden" scope={ valueheader="cbi/cell_valueheader" , valuefooter="cbi/cell_valuefooter" }
-%>
<%- local isempty = true
for i, k in ipairs(self.serverTable) do
section = k
isempty = false
local fc = (section.name == self.current) and "fast" or ""
local flag_icon = (section.flag ~= nil) and "flag-icon-" .. section.flag or "flag-icon-un"
local switch_enable = (section.switch_enable == "1") and "" or "hidden"
scope = { valueheader = "cbi/cell_valueheader", valuefooter = "cbi/cell_valuefooter" }
-%>
<div class="pure-u-1-5">
<div class="cbi-section-table-row <%=fc %> " id="cbi-<%=self.config%>-<%=section.name%>" data-flag="<%=section.flag%>" server="<%=section.server%>" server_port="<%=section.server_port%>">
<div class="loadings hide"></div>
<div class="incon type flag-icon <%=flag_icon %>" data-setction="<%=section.name%>">
<img class="pure-imgw <%=switch_enable %>" src="/luci-static/vssr/img/switch.png">
<div class="tp"><%=section.type%></div>
</div>
<div class="incon alias"><%=section.alias%></div>
<%- if self.extedit or self.addremove then -%>
<div class="cbi-section-table-cell">
<div class="host_con"></div>
<a class="cbi-button ssr-button" type="button" value="" onclick="apply_node('<%=section.name%>')"
alt="<%:Apply%>" title="<%:Apply%>"><span class="icon-use"></span> <%:Apply%></a>
<%- if self.extedit then -%>
<a class="cbi-button ssr-button " type="button" value="" <%- if type(self.extedit) == "string" then
%> onclick="location.href='<%=self.extedit:format(section.name)%>'" <%- elseif type(self.extedit) == "function" then
%> onclick="location.href='<%=self:extedit(section.name)%>'" <%- end
%> alt="<%:Edit%>" title="<%:Edit%>"><span class="icon-edit"></span> <%:Edit%></a>
<%- end; if self.addremove then %>
<a class="cbi-button ssr-button" type="button" value="" onclick="delete_node('<%=section.name%>')"
alt="<%:Delete%>" title="<%:Delete%>" /><span
class="icon-delete"></span> <%:Delete%></a>
<%- end -%>
<div class="pure-u-1-5">
<div class="cbi-section-table-row <%=fc %> " id="cbi-<%=self.config%>-<%=section.name%>"
data-flag="<%=section.flag%>" server="<%=section.server%>"
server_port="<%=section.server_port%>">
<div class="loadings hide"></div>
<div class="incon type flag-icon <%=flag_icon %>" data-setction="<%=section.name%>">
<img class="pure-imgw <%=switch_enable %>" src="/luci-static/vssr/img/switch.png">
<div class="tp">
<%=section.type%>
</div>
</div>
<div class=" alias">
<%=section.alias%>
</div>
<%- if self.extedit or self.addremove then -%>
<div class="cbi-section-table-cell">
<div class="host_con"></div>
<a class="cbi-button ssr-button" type="button" value=""
onclick="apply_node('<%=section.name%>')" alt="<%:Apply%>"
title="<%:Apply%>"><span class="icon-use"></span>
<%:Apply%>
</a>
<%- if self.extedit then -%>
<a class="cbi-button ssr-button " type="button" value="" <%- if type(self.extedit) == "string" then
%> onclick="location.href='<%=self.extedit:format(section.name)%>'" <%- elseif type(self.extedit) == "function" then
%> onclick="location.href='<%=self:extedit(section.name)%>'" <%- end
%> alt="<%:Edit%>" title="<%:Edit%>"><span class="icon-edit"></span> <%:Edit%></a>
<%- end; if self.addremove then %>
<a class="cbi-button ssr-button" type="button" value=""
onclick="delete_node('<%=section.name%>')" alt="<%:Delete%>"
title="<%:Delete%>" /><span class="icon-delete"></span>
<%:Delete%></a>
<%- end -%>
</div>
<%- end -%>
</div>
</div>
<%- end -%>
<%- if isempty then -%>
<div class="cbi-section-table-row">
<div colspan="<%=count%>"><em><br />
<%:This section contains no values yet%>
</em></div>
</div>
<%- end -%>
</div>
<% if self.error then %>
<div class="cbi-section-error">
<ul>
<% for _, c in pairs(self.error) do for _, e in ipairs(c) do -%>
<li>
<%=pcdata(e):gsub("\n","<br />")%>
</li>
<%- end end %>
</ul>
</div>
</div>
<%- end -%>
<% end %>
<%- if isempty then -%>
<div class="cbi-section-table-row">
<div colspan="<%=count%>"><em><br /><%:This section contains no values yet%></em></div>
</div>
<%- end -%>
</div>
<% if self.error then %>
<div class="cbi-section-error">
<ul><% for _, c in pairs(self.error) do for _, e in ipairs(c) do -%>
<li><%=pcdata(e):gsub("\n","<br />")%></li>
<%- end end %></ul>
</div>
<% end %>
<%- if self.addremove then -%>
<% if self.template_addremove then include(self.template_addremove) else -%>
<div class="cbi-section-create cbi-tblsection-create">
<% if self.anonymous then %>
<input class="cbi-button cbi-button-add" type="submit" value="<%:Add%>"
name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" title="<%:Add%>" />
<% else %>
<% if self.invalid_cts then -%><div class="cbi-section-error"><% end %>
<input type="text" class="cbi-section-create-name"
id="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>"
name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" data-type="uciname"
data-optional="true" />
<input class="cbi-button cbi-button-add" type="submit"
onclick="this.form.cbi_state = 'add-section'; return true" value="<%:Add%>" title="<%:Add%>" />
<% if self.invalid_cts then -%>
<br /><%:Invalid%></div>
<%- end %>
<% end %>
</div>
<%- end %>
<%- end -%>
<%- if self.addremove then -%>
<% if self.template_addremove then include(self.template_addremove) else -%>
<div class="cbi-section-create cbi-tblsection-create">
<% if self.anonymous then %>
<input class="cbi-button cbi-button-add" type="submit" value="<%:Add%>"
name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>"
title="<%:Add%>" />
<% else %>
<% if self.invalid_cts then -%>
<div class="cbi-section-error">
<% end %>
<input type="text" class="cbi-section-create-name"
id="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>"
name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>"
data-type="uciname" data-optional="true" />
<input class="cbi-button cbi-button-add" type="submit"
onclick="this.form.cbi_state = 'add-section'; return true"
value="<%:Add%>" title="<%:Add%>" />
<% if self.invalid_cts then -%>
<br />
<%:Invalid%>
</div>
<%- end %>
<% end %>
</div>
<%- end %>
<%- end -%>
</div>
</fieldset>
<!-- /tblsection -->
@ -120,15 +146,15 @@
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="global" data-node="' + node + '"> 主服务器 </button></div></div>';
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="udp_relay" data-node="' + node + '"> UDP游戏模式 </button></div></div>';
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="youtube" data-node="' + node + '"> Youtube </button></div></div>';
if ($('#cbi-' + CONFIG + '-' + node).attr("data-flag") == "tw") {
//if ($('#cbi-' + CONFIG + '-' + node).attr("data-flag") == "tw") {
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="tw_video" data-node="' + node + '"> TW Video </button></div></div>';
}
//}
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="netflix" data-node="' + node + '"> Netflix </button></div></div>';
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="disney" data-node="' + node + '"> Diseny+ </button></div></div>';
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="prime" data-node="' + node + '"> Prime Video </button></div></div>';
if ($('#cbi-' + CONFIG + '-' + node).attr("data-flag") == "hk") {
//if ($('#cbi-' + CONFIG + '-' + node).attr("data-flag") == "hk") {
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="tvb" data-node="' + node + '"> TVB Video </button></div></div>';
}
//}
$html += '<div class="pure-u-1-2"><div class="gap"><button class="cbi-button cbi-button-apply change-node" data-server="custom" data-node="' + node + '"> 自定义 </button></div></div>';
$html += '</div>';
Swal.fire({
@ -165,9 +191,9 @@
}
})
}
//删除节点
function delete_node(node){
function delete_node(node) {
XHR.halt();
$.each(ajaxArray, function (n, value) { value.abort(); }) //中断所有的ajax请求
$.get(DELETE_NODE_URL, { node: node },
@ -223,10 +249,7 @@
function (data, status) {
currentCheckCount++
var host_con = $(target).find(".host_con");
host_con.removeClass("fast");
host_con.removeClass("middle");
host_con.removeClass("slow");
host_con.removeClass("nopass");
host_con.removeClass("fast middle slow nopass");
if (data.ret == 1) {
if (data.used == "") {
host_con.addClass("nopass");

View File

@ -1,5 +1,6 @@
<%+cbi/valueheader%>
<link rel="stylesheet" href="/luci-static/vssr/css/vssr.css?v=<%=math.random(1,100000)%>">
<script src="/luci-static/vssr/jquery.min.js"></script>
<label class="cbi-value-title"><%= translate("Update") %></label>
<div class="cbi-value-field">
<input class="cbi-button cbi-button-reload" id="update_subscribe" type="button" size="0"
@ -7,7 +8,7 @@
</div>
<script type="text/javascript">
const SAVE_SUBSCRIBE_URL = '<%=luci.dispatcher.build_url("admin", "services", "vssr","subscribe")%>';
const SERVERS_URL = '<%=luci.dispatcher.build_url("admin", "services", "vssr","servers")%>';
@ -20,14 +21,14 @@
'<textarea cols="63" rows="28" wrap="on" readonly="readonly" id="log_content3" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>' +
'</div>' +
'</div>';
$(document).ready(function () {
//显示并开始刷新订阅
function update_subscribe() {
$("body").append(modal);
$(".modals-bg").removeClass("hide");
setTimeout(function(){
$(".modals").removeClass("hide");
}, 200);
}, 100);
setTimeout("get_realtime_log();", 500);
}
//保存订阅按钮
@ -76,7 +77,7 @@
});
return false;
});
});
function get_realtime_log() {
$.ajax({
@ -106,7 +107,7 @@
}
});
}
</script>
<%+cbi/valuefooter%>

View File

@ -128,13 +128,13 @@ msgid "SSR Server"
msgstr "服务端"
msgid "vssr Server"
msgstr "vssr 服务端"
msgstr "Hello World 服务端"
msgid "vssr Server is running"
msgstr "vssr 服务端运行中"
msgstr "Hello World 服务端运行中"
msgid "vssr Server is not running"
msgstr "vssr 服务端未运行"
msgstr "Hello World 服务端未运行"
msgid "Enable Server"
msgstr "启动服务端"
@ -710,3 +710,15 @@ msgstr "TVB 域名"
msgid "Custom Domain"
msgstr "自定义域名"
msgid "Subscribe"
msgstr "订阅设置"
msgid "Local Proxy"
msgstr "本地代理"
msgid "↑ Put your IP list here"
msgstr "↑ 在上面放置你需要分流的IP列表"
msgid "↑ Put your domain list here"
msgstr "↑ 在上面放置你需要分流的域名列表"

View File

@ -609,6 +609,7 @@ EOF
/etc/init.d/dnsmasq restart >/dev/null 2>&1
start_server
start_local
scount=$(count_shunt)
if [ $scount != "0" ]; then
start_shunt
fi

View File

@ -1,6 +1,7 @@
local ucursor = require 'luci.model.uci'.cursor()
local name = 'vssr'
local json = require 'luci.jsonc'
local nixio = require 'nixio'
local server_section = arg[1]
local proto = arg[2]
local local_port = arg[3]
@ -8,6 +9,9 @@ local outbounds_table = {}
local rules_table = {}
function read_conf(file)
if not nixio.fs.access(file) then
return nil
end
local rfile = io.open(file, "r")
local ltable = {}
for line in rfile:lines() do
@ -18,15 +22,30 @@ function read_conf(file)
return rtable
end
local v2ray_flow = ucursor:get_first(name, 'global', 'v2ray_flow', '0')
local custom_domain = read_conf("/etc/vssr/custom_domain.list")
local custom_ip = read_conf("/etc/vssr/custom_ip.list")
local youtube_domain = read_conf("/etc/vssr/youtube_domain.list")
local youtube_ip = read_conf("/etc/vssr/youtube_ip.list")
local tw_video_domain = read_conf("/etc/vssr/tw_video_domain.list")
local tw_video_ip = read_conf("/etc/vssr/tw_video_ip.list")
local netflix_domain = read_conf("/etc/vssr/netflix_domain.list")
local netflix_ip = read_conf("/etc/vssr/netflix_ip.list")
local disney_domain = read_conf("/etc/vssr/disney_domain.list")
local disney_ip = read_conf("/etc/vssr/disney_ip.list")
local prime_domain = read_conf("/etc/vssr/prime_domain.list")
local prime_ip = read_conf("/etc/vssr/prime_ip.list")
local tvb_domain = read_conf("/etc/vssr/tvb_domain.list")
local tvb_ip = read_conf("/etc/vssr/tvb_ip.list")
local flow_table = {
yotube = {
@ -35,6 +54,7 @@ local flow_table = {
rules = {
type = 'field',
domain = youtube_domain,
ip = youtube_ip,
outboundTag = 'youtube'
}
},
@ -44,6 +64,7 @@ local flow_table = {
rules = {
type = 'field',
domain = tw_video_domain,
ip = tw_video_ip,
outboundTag = 'tw_video'
}
},
@ -53,6 +74,7 @@ local flow_table = {
rules = {
type = 'field',
domain = netflix_domain,
ip = netflix_ip,
outboundTag = 'netflix'
}
},
@ -62,6 +84,7 @@ local flow_table = {
rules = {
type = 'field',
domain = disney_domain,
ip = disney_ip,
outboundTag = 'disney'
}
},
@ -71,6 +94,7 @@ local flow_table = {
rules = {
type = 'field',
domain = prime_domain,
ip = prime_ip,
outboundTag = 'prime'
}
},
@ -80,6 +104,7 @@ local flow_table = {
rules = {
type = 'field',
domain = tvb_domain,
ip = tvb_ip,
outboundTag = 'tvb'
}
},
@ -89,6 +114,7 @@ local flow_table = {
rules = {
type = 'field',
domain = custom_domain,
ip = custom_ip,
outboundTag = 'custom'
}
}
@ -113,7 +139,7 @@ local bt_rules1 = {
'BitTorrent',
'announce_peer',
'announce.php?passkey='
},
}
}
function gen_outbound(server_node, tags, local_ports)
@ -210,12 +236,30 @@ function gen_bt_outbounds()
end
if v2ray_flow == '1' then
table.insert(outbounds_table, gen_outbound(server_section, 'global', 2080))
for _, v in pairs(flow_table) do
if(v.rules.domain ~= nil) then
if(v.rules.domain ~= nil or v.rules.ip ~= nil) then
local server = ucursor:get_first(name, 'global', v.name .. '_server')
table.insert(outbounds_table, gen_outbound(server, v.name, v.port))
table.insert(rules_table, (server ~= nil and server ~= 'nil' ) and v.rules or nil)
if(v.rules.domain ~= nil) then
domain_rules = {
type = 'field',
domain = v.rules.domain,
outboundTag = v.rules.outboundTag
}
table.insert(rules_table, (server ~= nil and server ~= 'nil' ) and domain_rules or nil)
end
if(v.rules.ip ~= nil) then
ip_rules = {
type = 'field',
ip = v.rules.ip,
outboundTag = v.rules.outboundTag
}
table.insert(rules_table, (server ~= nil and server ~= 'nil' ) and ip_rules or nil)
end
end
end
else
@ -246,6 +290,6 @@ local v2ray = {
},
-- 传出连接
outbounds = outbounds_table,
routing = {domainStrategy = 'AsIs', rules = rules_table}
routing = {domainStrategy = 'IPIfNonMatch', rules = rules_table}
}
print(json.stringify(v2ray, 1))

View File

@ -33,6 +33,40 @@ local switch = '0'
local subscribe_url = ucic:get_first(name, 'server_subscribe', 'subscribe_url', {})
local filter_words = ucic:get_first(name, 'server_subscribe', 'filter_words', '过期时间/剩余流量')
function print_r ( t )
local print_r_cache={}
local function sub_print_r(t,indent)
if (print_r_cache[tostring(t)]) then
print(indent.."*"..tostring(t))
else
print_r_cache[tostring(t)]=true
if (type(t)=="table") then
for pos,val in pairs(t) do
if (type(val)=="table") then
print(indent.."["..pos.."] => "..tostring(t).." {")
sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))
print(indent..string.rep(" ",string.len(pos)+6).."}")
elseif (type(val)=="string") then
print(indent.."["..pos..'] => "'..val..'"')
else
print(indent.."["..pos.."] => "..tostring(val))
end
end
else
print(indent..tostring(t))
end
end
end
if (type(t)=="table") then
print(tostring(t).." {")
sub_print_r(t," ")
print("}")
else
sub_print_r(t," ")
end
print()
end
local log = function(...)
print(os.date('%Y-%m-%d %H:%M:%S ') .. table.concat({...}, ' '))
end
@ -55,6 +89,43 @@ local function split(full, sep)
end
return result
end
--table去重
local function clone( object )
local lookup_table = {}
local function copyObj( object )
if type( object ) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local new_table = {}
lookup_table[object] = new_table
for key, value in pairs( object ) do
new_table[copyObj( key )] = copyObj( value )
end
return setmetatable( new_table, getmetatable( object ) )
end
return copyObj( object )
end
local function table_unique(list)
local temp1 = clone(list)
local temp2 = clone(list)
for k1, v1 in ipairs(temp1) do
for k2, v2 in ipairs(temp2) do
if v1.alias ~= v2.alias and v1.hashkey == v2.hashkey then
table.remove(temp1, k1)
table.remove(temp2, k1)
end
end
end
return temp1
end
-- urlencode
local function get_urlencode(c)
return sformat('%%%02X', sbyte(c))
@ -385,12 +456,21 @@ local execute = function()
end
end
log('成功解析节点数量: ' .. #nodes)
end
else
log(url .. ': 获取内容为空')
end
end
end
-- diff
do
assert(next(nodeResult), '获取不到节点信息,请检查路由器是否能够访问网络,或者订阅链接是否正确')
if next(nodeResult) == nil then
log("更新失败,没有可用的节点信息")
if proxy == '0' then
luci.sys.init.start(name)
log('订阅失败, 恢复服务')
end
return
end
local add, del = 0, 0
ucic:foreach(
name,
@ -407,17 +487,24 @@ local execute = function()
setmetatable(nodeResult[old.grouphashkey][old.hashkey], {__index = {_ignore = true}})
end
else
if (old.alias ~= nil) then
log('忽略手动添加的节点: ' .. old.alias)
if not old.alias then
if not old.server or old.server_port then
ucic:delete(name, old['.name'])
else
old.alias = old.server .. ':' .. old.server_port
log('忽略手动添加的节点: ' .. old.alias)
end
else
log('忽略手动添加的无效节点')
log('忽略手动添加的节点: ' .. old.alias)
end
end
end
)
for k, v in ipairs(nodeResult) do
for kk, vv in ipairs(v) do
-- 如果订阅节点中有相同的节点信息 需要先去重。
new_nodes = table_unique(v)
for kk, vv in ipairs(new_nodes) do
if not vv._ignore then
local section = ucic:add(name, uciType)
ucic:tset(name, section, vv)

View File

@ -16,11 +16,7 @@ local log = function(...)
end
log('正在更新【GFW列表】数据库')
if nixio.fs.access('/usr/bin/wget-ssl') then
refresh_cmd = 'wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O /tmp/gfw.b64'
else
refresh_cmd = 'wget -O /tmp/gfw.b64 http://iytc.net/tools/list.b64'
end
refresh_cmd = 'wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O /tmp/gfw.b64'
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
if sret == 0 then
luci.sys.call('/usr/bin/vssr-gfw')
@ -43,7 +39,7 @@ else
end
log('正在更新【国内IP段】数据库')
refresh_cmd ="wget -O- 'https://ispip.clang.cn/all_cn.txt' > /tmp/china_ssr.txt 2>/dev/null"
refresh_cmd ="wget-ssl -O- 'https://ispip.clang.cn/all_cn.txt' > /tmp/china_ssr.txt 2>/dev/null"
sret = luci.sys.call(refresh_cmd)
icount = luci.sys.exec('cat /tmp/china_ssr.txt | wc -l')
if sret == 0 then
@ -69,12 +65,8 @@ end
if ucic:get_first('vssr', 'global', 'adblock', '') == '1' then
log('正在更新【广告屏蔽】数据库')
local need_process = 0
if nixio.fs.access('/usr/bin/wget-ssl') then
refresh_cmd = 'wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf'
need_process = 1
else
refresh_cmd = 'wget -O /tmp/ad.conf http://iytc.net/tools/ad.conf'
end
refresh_cmd = 'wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf'
need_process = 1
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
if sret == 0 then
if need_process == 1 then

View File

@ -0,0 +1,232 @@
/*!
Pure v1.0.1
Copyright 2013 Yahoo!
Licensed under the BSD License.
https://github.com/pure-css/pure/blob/master/LICENSE.md
*/
.pure-g {
letter-spacing: -.31em;
text-rendering: optimizespeed;
font-family: FreeSans, Arimo, "Droid Sans", Helvetica, Arial, sans-serif;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-flow: row wrap;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
-webkit-align-content: flex-start;
-ms-flex-line-pack: start;
align-content: flex-start
}
@media all and (-ms-high-contrast:none),
(-ms-high-contrast:active) {
table .pure-g {
display: block
}
}
.opera-only :-o-prefocus,
.pure-g {
word-spacing: -.43em
}
.pure-u {
display: inline-block;
zoom: 1;
letter-spacing: normal;
word-spacing: normal;
vertical-align: top;
text-rendering: auto
}
.pure-g [class*=pure-u] {
font-family: sans-serif
}
.pure-u-1,
.pure-u-1-1,
.pure-u-1-12,
.pure-u-1-2,
.pure-u-1-24,
.pure-u-1-3,
.pure-u-1-4,
.pure-u-1-5,
.pure-u-1-6,
.pure-u-1-8,
.pure-u-10-24,
.pure-u-11-12,
.pure-u-11-24,
.pure-u-12-24,
.pure-u-13-24,
.pure-u-14-24,
.pure-u-15-24,
.pure-u-16-24,
.pure-u-17-24,
.pure-u-18-24,
.pure-u-19-24,
.pure-u-2-24,
.pure-u-2-3,
.pure-u-2-5,
.pure-u-20-24,
.pure-u-21-24,
.pure-u-22-24,
.pure-u-23-24,
.pure-u-24-24,
.pure-u-3-24,
.pure-u-3-4,
.pure-u-3-5,
.pure-u-3-8,
.pure-u-4-24,
.pure-u-4-5,
.pure-u-5-12,
.pure-u-5-24,
.pure-u-5-5,
.pure-u-5-6,
.pure-u-5-8,
.pure-u-6-24,
.pure-u-7-12,
.pure-u-7-24,
.pure-u-7-8,
.pure-u-8-24,
.pure-u-9-24 {
display: inline-block;
zoom: 1;
letter-spacing: normal;
word-spacing: normal;
vertical-align: top;
text-rendering: auto
}
.pure-u-1-24 {
width: 4.1667%
}
.pure-u-1-12,
.pure-u-2-24 {
width: 8.3333%
}
.pure-u-1-8,
.pure-u-3-24 {
width: 12.5%
}
.pure-u-1-6,
.pure-u-4-24 {
width: 16.6667%
}
.pure-u-1-5 {
width: 20%
}
.pure-u-5-24 {
width: 20.8333%
}
.pure-u-1-4,
.pure-u-6-24 {
width: 25%
}
.pure-u-7-24 {
width: 29.1667%
}
.pure-u-1-3,
.pure-u-8-24 {
width: 33.3333%
}
.pure-u-3-8,
.pure-u-9-24 {
width: 37.5%
}
.pure-u-2-5 {
width: 40%
}
.pure-u-10-24,
.pure-u-5-12 {
width: 41.6667%
}
.pure-u-11-24 {
width: 45.8333%
}
.pure-u-1-2,
.pure-u-12-24 {
width: 50%
}
.pure-u-13-24 {
width: 54.1667%
}
.pure-u-14-24,
.pure-u-7-12 {
width: 58.3333%
}
.pure-u-3-5 {
width: 60%
}
.pure-u-15-24,
.pure-u-5-8 {
width: 62.5%
}
.pure-u-16-24,
.pure-u-2-3 {
width: 66.6667%
}
.pure-u-17-24 {
width: 70.8333%
}
.pure-u-18-24,
.pure-u-3-4 {
width: 75%
}
.pure-u-19-24 {
width: 79.1667%
}
.pure-u-4-5 {
width: 80%
}
.pure-u-20-24,
.pure-u-5-6 {
width: 83.3333%
}
.pure-u-21-24,
.pure-u-7-8 {
width: 87.5%
}
.pure-u-11-12,
.pure-u-22-24 {
width: 91.6667%
}
.pure-u-23-24 {
width: 95.8333%
}
.pure-u-1,
.pure-u-1-1,
.pure-u-24-24,
.pure-u-5-5 {
width: 100%
}

View File

@ -1,245 +1,73 @@
@import url("flag-icon.min.css?v=1.16");
@import url("sweetalert2.css?v=1.16");
/*!
Pure v1.0.1
Copyright 2013 Yahoo!
Licensed under the BSD License.
https://github.com/pure-css/pure/blob/master/LICENSE.md
*/
@import url("pure.css?v=1.16");
.pure-g {
letter-spacing: -.31em;
text-rendering: optimizespeed;
font-family: FreeSans, Arimo, "Droid Sans", Helvetica, Arial, sans-serif;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-flow: row wrap;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
-webkit-align-content: flex-start;
-ms-flex-line-pack: start;
align-content: flex-start
/** Common **/
.pure-img {
max-height: 100%;
width: auto;
}
@media all and (-ms-high-contrast:none),
(-ms-high-contrast:active) {
table .pure-g {
display: block
}
.pure-imgw {
max-width: 100%;
height: auto;
}
.opera-only :-o-prefocus,
.pure-g {
word-spacing: -.43em
}
.pure-u {
display: inline-block;
zoom: 1;
letter-spacing: normal;
word-spacing: normal;
vertical-align: top;
text-rendering: auto
}
.pure-g [class*=pure-u] {
font-family: sans-serif
}
.pure-u-1,
.pure-u-1-1,
.pure-u-1-12,
.pure-u-1-2,
.pure-u-1-24,
.pure-u-1-3,
.pure-u-1-4,
.pure-u-1-5,
.pure-u-1-6,
.pure-u-1-8,
.pure-u-10-24,
.pure-u-11-12,
.pure-u-11-24,
.pure-u-12-24,
.pure-u-13-24,
.pure-u-14-24,
.pure-u-15-24,
.pure-u-16-24,
.pure-u-17-24,
.pure-u-18-24,
.pure-u-19-24,
.pure-u-2-24,
.pure-u-2-3,
.pure-u-2-5,
.pure-u-20-24,
.pure-u-21-24,
.pure-u-22-24,
.pure-u-23-24,
.pure-u-24-24,
.pure-u-3-24,
.pure-u-3-4,
.pure-u-3-5,
.pure-u-3-8,
.pure-u-4-24,
.pure-u-4-5,
.pure-u-5-12,
.pure-u-5-24,
.pure-u-5-5,
.pure-u-5-6,
.pure-u-5-8,
.pure-u-6-24,
.pure-u-7-12,
.pure-u-7-24,
.pure-u-7-8,
.pure-u-8-24,
.pure-u-9-24 {
display: inline-block;
zoom: 1;
letter-spacing: normal;
word-spacing: normal;
vertical-align: top;
text-rendering: auto
}
.pure-u-1-24 {
width: 4.1667%
}
.pure-u-1-12,
.pure-u-2-24 {
width: 8.3333%
}
.pure-u-1-8,
.pure-u-3-24 {
width: 12.5%
}
.pure-u-1-6,
.pure-u-4-24 {
width: 16.6667%
}
.pure-u-1-5 {
width: 20%
}
.pure-u-5-24 {
width: 20.8333%
}
.pure-u-1-4,
.pure-u-6-24 {
width: 25%
}
.pure-u-7-24 {
width: 29.1667%
}
.pure-u-1-3,
.pure-u-8-24 {
width: 33.3333%
}
.pure-u-3-8,
.pure-u-9-24 {
width: 37.5%
}
.pure-u-2-5 {
width: 40%
}
.pure-u-10-24,
.pure-u-5-12 {
width: 41.6667%
}
.pure-u-11-24 {
width: 45.8333%
}
.pure-u-1-2,
.pure-u-12-24 {
width: 50%
}
.pure-u-13-24 {
width: 54.1667%
}
.pure-u-14-24,
.pure-u-7-12 {
width: 58.3333%
}
.pure-u-3-5 {
width: 60%
}
.pure-u-15-24,
.pure-u-5-8 {
width: 62.5%
display: flex;
align-items: center;
}
.pure-u-16-24,
.pure-u-2-3 {
width: 66.6667%
.gap {
margin-right: 0.5rem;
}
.pure-u-17-24 {
width: 70.8333%
/** 复写theme **/
.cbi-section {
border: 0;
border-radius: .375rem;
overflow-x: auto;
overflow-y: hidden;
}
.pure-u-18-24,
.pure-u-3-4 {
width: 75%
.cbi-section-node {
border: 0;
border-radius: .375rem;
margin-bottom: 0px;
overflow-x: auto;
overflow-y: hidden;
padding: 0rem 0;
}
.pure-u-19-24 {
width: 79.1667%
#cbi-vssr {
overflow-x: hidden;
}
.pure-u-4-5 {
width: 80%
}
.pure-u-20-24,
.pure-u-5-6 {
width: 83.3333%
}
.pure-u-21-24,
.pure-u-7-8 {
width: 87.5%
}
.pure-u-11-12,
.pure-u-22-24 {
width: 91.6667%
}
.pure-u-23-24 {
width: 95.8333%
}
.pure-u-1,
.pure-u-1-1,
.pure-u-24-24,
.pure-u-5-5 {
width: 100%
#cbi-vssr .panel-title {
width: 100%;
display: block;
margin-bottom: 0;
padding: .8755rem 1.5rem;
margin-bottom: 0rem;
letter-spacing: .1rem;
font-weight: 600;
box-sizing: border-box;
}
/** Top StatusBar **/
.status {
margin: 1rem -0.5rem 1rem -0.5rem;
margin: 0.5rem -0.5rem 1rem -0.5rem;
}
.block {
.status .block {
margin: 0.5rem 0.5rem;
padding: 0;
font-weight: normal;
@ -255,56 +83,28 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
box-shadow: 0 0 2rem 0 rgba(136, 152, 170, .15);
}
.img-con {
.status .block .img-con {
margin: 1rem;
}
.pure-img {
max-height: 100%;
width: auto;
}
.pure-imgw {
max-width: 100%;
height: auto;
}
.green {
.status .block .green {
font-size: 1.25rem;
color: #2dce89;
}
.red {
.status .block .red {
font-size: 1.25rem;
color: #fb6340;
}
.sk-text-success {
color: #2dce89;
}
.sk-text-error {
color: #fb6340;
}
.gap {
margin-right: 0.5rem;
}
.block img {
.status .block img {
width: 48px;
height: auto;
float: right;
}
.pure-u-5-8 {
display: flex;
align-items: center;
}
.block h4 {
.status .block h4 {
font-size: .8125rem;
font-weight: 600;
margin: 1rem;
@ -312,12 +112,10 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
line-height: 1.8em;
}
.p-in5 {
padding: 8px;
}
/** Server List **/
.flag-icon:before {
position: absolute;
.p-in5 {
margin: 8px !important;
}
.cbi-section-table-row {
@ -346,6 +144,17 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
color: #fff;
}
.ssr-button:link,
.ssr-button:hover,
.ssr-button:focus,
.ssr-button:visited,
.ssr-button:active {
outline: 0;
text-decoration: none;
box-shadow: none;
}
.cbi-section-table-row.fast .ssr-button {
color: #fff;
}
@ -363,6 +172,15 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
color: #fff !important;
}
.host_con {
position: absolute;
left: 0;
width: 70px;
text-align: left;
height: 22px;
font-weight: bold;
}
.host_con.fast {
color: #6f9a37;
}
@ -379,7 +197,19 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
color: #fb6340;
}
.host_ok {
color: #fff;
background: #2dce89;
padding: 0.1rem 0.5rem;
border-radius: 0.2rem;
}
.host_error {
color: #fff;
background: #f5365c;
padding: 0.1rem 0.5rem;
border-radius: 0.2rem;
}
.loadings.hide {
opacity: 0;
@ -392,20 +222,20 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
height: 30px;
}
.flag-icon:before {
position: absolute;
}
.alias {
margin-bottom: 1px;
padding-left: 0px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.incon {
cursor: pointer;
}
.incon .pure-imgw {
transition: all 0.2s;
}
.incon:nth-child(2) {
position: absolute;
left: 0;
top: 0;
@ -414,10 +244,13 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
border: 0;
border-right: #d1dfed 1px solid;
background-position: top;
}
.incon:nth-child(2) .tp {
.incon .pure-imgw {
transition: all 0.2s;
}
.incon .tp {
position: absolute;
left: 0;
bottom: 0;
@ -430,34 +263,29 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
background: #525f7f;
}
.incon:nth-child(3) {
padding-left: 0px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.incon:nth-child(5),
.incon:nth-child(6) {
display: none;
}
.cbi-section-table-cell {
text-align: right;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
position: relative;
}
.ssr-button {
background: none;
border: none;
color: #525f7f;
padding: 0 0 0 0;
padding: 0 0.2rem 0 0;
height: auto;
line-height: 1.5em;
box-shadow: none;
}
.ssr-button:hover,
.ssr-button:focus,
.ssr-button:active {
color: #525f7f;
outline: 0;
text-decoration: none;
box-shadow: none;
@ -472,37 +300,18 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md
color: #fff !important;
background-color: #337ab7 !important;
border-color: #2e6da4 !important;
background-image: none;
float: right;
margin-right: 18px;
margin-top: 1rem;
margin-top: .25rem !important;
outline: none;
}
.cbi-section-table-cell {
position: relative;
.cbi-button-check:focus {
outline: none;
}
.host_con {
position: absolute;
left: 0;
width: 70px;
text-align: left;
height: 22px;
font-weight: bold;
}
.host_ok {
color: #fff;
background: #2dce89;
padding: 0.1rem 0.5rem;
border-radius: 0.2rem;
}
.host_error {
color: #fff;
background: #f5365c;
padding: 0.1rem 0.5rem;
border-radius: 0.2rem;
}
/** Bottom StatusBar **/
footer.mobile-hide {
display: block;
@ -537,6 +346,7 @@ footer.mobile-hide {
.status-bar .inner .status-info {
font-weight: bold;
line-height: 1.5em;
}
.status-bar .icon-con {
@ -544,6 +354,8 @@ footer.mobile-hide {
text-align: right;
}
/** Node choose panel **/
.choose_node .gap {
margin: 0.5rem 1rem;
position: relative;
@ -553,66 +365,8 @@ footer.mobile-hide {
width: 100% !important;
}
@media screen and (max-width: 2000px) {
.pure-u-1-5 {
width: 25%;
}
}
@media screen and (max-width: 1600px) {
.pure-u-1-5 {
width: 33.33333333%;
}
}
@media screen and (max-width: 1200px) {
.pure-u-1-5 {
width: 50%;
}
.status .pure-u-1-5 {
width: 33.333%;
}
}
@media screen and (max-width: 700px) {
.pure-u-1-4 {
width: 50%;
}
.pure-u-1-2 {
width: 100%;
}
.pure-u-1-5 {
width: 100%;
font-size: 14px;
}
.status .pure-u-1-5 {
width: 50%;
}
.cbi-button-add {
position: fixed;
padding: 0.3rem 0.5rem;
z-index: 1000;
width: 50px !important;
height: 50px;
bottom: 90px;
right: 5px;
font-size: 16px;
border-radius: 50%;
display: block;
background-color: #fb6340 !important;
border-color: #fb6340 !important;
box-shadow: 0 0 1rem 0 rgba(136, 152, 170, .75);
}
.choose_node .pure-u-1-2 {
width: 50%;
}
}
/** Subscribe panel **/
.modals-bg {
position: fixed;
@ -625,7 +379,7 @@ footer.mobile-hide {
transition: all 0.2s;
}
.modals-bg.hide{
.modals-bg.hide {
visibility: hidden;
opacity: 0;
}
@ -651,7 +405,7 @@ footer.mobile-hide {
transform: scale(1);
}
.modals.hide{
.modals.hide {
visibility: hidden;
opacity: 0;
transform: scale(0.5);
@ -688,7 +442,27 @@ footer.mobile-hide {
overflow: hidden
}
@media screen and (max-width: 1024px) {
@media screen and (max-width: 2000px) {
.pure-u-1-5 {
width: 25%;
}
}
@media screen and (max-width: 1600px) {
.pure-u-1-5 {
width: 33.33333333%;
}
}
@media screen and (max-width: 1200px) {
.pure-u-1-5 {
width: 50%;
}
.status .pure-u-1-5 {
width: 33.333%;
}
.modals {
position: fixed;
z-index: 100;
@ -704,6 +478,45 @@ footer.mobile-hide {
}
@media screen and (max-width: 700px) {
.pure-u-1-4 {
width: 50%;
}
.pure-u-1-2 {
width: 100%;
}
.pure-u-1-5 {
width: 100%;
font-size: 14px;
}
.status .pure-u-1-5 {
width: 50%;
}
.cbi-button-add {
position: fixed;
padding: 0.3rem 0.5rem;
z-index: 1000;
width: 50px !important;
height: 50px !important;
bottom: 90px;
color: #fff;
right: 5px;
font-size: 16px;
border-radius: 50%;
display: block;
background-color: #fb6340 !important;
border-color: #fb6340 !important;
box-shadow: 0 0 1rem 0 rgba(136, 152, 170, .75);
background-image: none;
}
.choose_node .pure-u-1-2 {
width: 50%;
}
.modals-bg {
position: fixed;
z-index: 100000;
@ -732,6 +545,14 @@ footer.mobile-hide {
height: 2.5em;
text-align: right;
}
.p-in5 {
padding-bottom: 3rem;
}
.cbi-page-actions {
padding-bottom: 4rem !important;
}
}
@media (prefers-color-scheme: dark) {
@ -753,4 +574,5 @@ footer.mobile-hide {
.ssr-button {
color: #ccc;
}
}

View File

@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=autocore
PKG_VERSION:=1
PKG_RELEASE:=36
PKG_RELEASE:=37
include $(INCLUDE_DIR)/package.mk

View File

@ -1,7 +1,6 @@
#!/bin/sh
cpu_arch="$(cat "/proc/cpuinfo" | grep "model name" | sed -n "1p" | awk -F ': ' '{print $2}')"
[ -z "${cpu_arch}" ] && cpu_arch="ARMv8 Processor"
cpu_cores="$(cat "/proc/cpuinfo" | grep "processor" | wc -l)"
if grep -q "bcm27xx" "/etc/openwrt_release"; then

View File

@ -31,7 +31,6 @@ ln -sf /sbin/ip /usr/bin/ip
sed -i 's#https://downloads.openwrt.org#https://mirrors.cloud.tencent.com/lede#g' /etc/opkg/distfeeds.conf
sed -i '/openwrt_luci/ { s/snapshots/releases\/18.06.9/g; }' /etc/opkg/distfeeds.conf
sed -i '/openwrt_packages/ { s/snapshots/releases\/19.07.5/g; }' /etc/opkg/distfeeds.conf
sed -i "s/# //g" /etc/opkg/distfeeds.conf
sed -i 's/root::0:0:99999:7:::/root:$1$V4UetPzk$CYXluq4wUazHjmCDBCqXF.:0:0:99999:7:::/g' /etc/shadow

View File

@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-ssr-plus
PKG_VERSION:=182
PKG_RELEASE:=5
PKG_RELEASE:=9
define Package/$(PKG_NAME)/conffiles
/etc/config/shadowsocksr
@ -10,69 +10,89 @@ define Package/$(PKG_NAME)/conffiles
endef
define Package/$(PKG_NAME)/config
config PACKAGE_$(PKG_NAME)_INCLUDE_Xray
bool "Include Xray"
default y if i386||x86_64||arm||aarch64
config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan
bool "Include Trojan"
default y if i386||x86_64||arm||aarch64
config PACKAGE_$(PKG_NAME)_INCLUDE_Redsocks2
bool "Include Redsocks2"
default y if i386||x86_64||arm||aarch64
config PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun
bool "Include Kcptun"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy
bool "Include NaiveProxy"
depends on !(arc||armeb||mips||mips64||powerpc)
default y if i386||x86_64||arm||aarch64
config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray
bool "Include V2ray"
config PACKAGE_$(PKG_NAME)_INCLUDE_Redsocks2
bool "Include Redsocks2"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Go
bool "Include Trojan-Go"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks
bool "Include Shadowsocks-libev"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun
bool "Include Kcptun"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_plugin
bool "Include Shadowsocks V2ray Plugin"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR
bool "Include ShadowsocksR-libev"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server
bool "Include ShadowsocksR Server"
default y if i386||x86_64||arm||aarch64
config PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs
bool "Include Shadowsocks Simple Obfs Plugin"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan
bool "Include Trojan"
default y if i386||arm
config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Go
bool "Include Trojan-Go"
default y if x86_64||aarch64
config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray
bool "Include V2ray"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin
bool "Include Shadowsocks V2ray Plugin"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_Xray
bool "Include Xray"
default y if i386||x86_64||arm||aarch64
endef
PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_plugin \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Xray \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Trojan \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Go \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Redsocks2 \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Trojan \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Go \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Xray
LUCI_TITLE:=SS/SSR/V2Ray/Trojan/NaiveProxy/Socks5/Tun LuCI interface
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+shadowsocksr-libev-alt +ipset +ip-full +iptables-mod-tproxy +dnsmasq-full +coreutils +coreutils-base64 +pdnsd-alt +wget-ssl +lua +libuci-lua \
+microsocks +dns2socks +shadowsocks-libev-ss-local +shadowsocksr-libev-ssr-local +shadowsocks-libev-ss-redir +simple-obfs +tcping +resolveip\
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_plugin:v2ray-plugin \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray \
+PACKAGE_$(PKG_NAME)_INCLUDE_Xray:xray \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:trojan \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Go:trojan-go \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:ipt2socks \
LUCI_DEPENDS:=+coreutils +coreutils-base64 +dns2socks +dnsmasq-full +ipset +ip-full \
+iptables-mod-tproxy +lua +libuci-lua +microsocks +pdnsd-alt +tcping +resolveip \
+shadowsocksr-libev-alt +wget-ssl \
+PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun:kcptun-client \
+PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy:naiveproxy \
+PACKAGE_$(PKG_NAME)_INCLUDE_Redsocks2:redsocks2 \
+PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun:kcptun-client \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server:shadowsocksr-libev-server
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks:shadowsocks-libev-ss-local \
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks:shadowsocks-libev-ss-redir \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR:shadowsocksr-libev-ssr-local \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server:shadowsocksr-libev-server \
+PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs:simple-obfs \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:trojan \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:ipt2socks \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Go:trojan-go \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin:v2ray-plugin \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray \
+PACKAGE_$(PKG_NAME)_INCLUDE_Xray:xray
include $(TOPDIR)/feeds/luci/luci.mk

View File

@ -361,8 +361,8 @@ function import_ssr_url(btn, urlname, sid) {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.vless_encryption')[0].value = queryParam.encryption || "none";
if (queryParam.security == "tls") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = queryParam.sni || serverPart[0];
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event);
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = queryParam.sni || serverPart[0];
}
switch (queryParam.type) {
case "ws":

View File

@ -44,7 +44,6 @@ CRON_FILE=/etc/crontabs/root
EXTRA_COMMANDS='reset'
EXTRA_HELP=" reset Reset to default settings"
#extra_command "reset" "Reset to default settings"
trap 'rm -f "$LOCK_FILE"; exit $?' INT TERM EXIT
uci_get_by_name() {
local ret=$(uci get $NAME.$1.$2 2>/dev/null)
@ -283,7 +282,7 @@ gen_config_file() { #server1 type2 code3 local_port4 socks_port5 threads5
vmess | vless)
lua /usr/share/shadowsocksr/gen_config.lua $1 $mode $4 $5 >$config_file
;;
trojan | trojan-go)
trojan)
case "$3" in
1)
lua /usr/share/shadowsocksr/gen_config.lua $1 nat $4 >$config_file
@ -292,10 +291,25 @@ gen_config_file() { #server1 type2 code3 local_port4 socks_port5 threads5
lua /usr/share/shadowsocksr/gen_config.lua $1 client $4 >$config_file
;;
3)
lua /usr/share/shadowsocksr/gen_config.lua $1 nat $4 >$config_file
lua /usr/share/shadowsocksr/gen_config.lua $1 client $tmp_port >$shunt_dns_config_file
;;
4)
lua /usr/share/shadowsocksr/gen_config.lua $1 $mode $4 >$config_file
lua /usr/share/shadowsocksr/gen_config.lua $1 client $4 >$config_file
;;
esac
;;
trojan-go)
case "$3" in
1 | 2)
lua /usr/share/shadowsocksr/gen_config.lua $1 nat $4 >$config_file
;;
3)
lua /usr/share/shadowsocksr/gen_config.lua $1 nat $4 >$config_file
lua /usr/share/shadowsocksr/gen_config.lua $1 client $tmp_port >$shunt_dns_config_file
;;
4)
lua /usr/share/shadowsocksr/gen_config.lua $1 client $4 >$config_file
;;
esac
;;
@ -342,20 +356,29 @@ start_udp() {
ln_start_bin $(first_type xray v2ray) v2ray -config $udp_config_file
echolog "UDP TPROXY Relay:$($(first_type "xray" "v2ray") -version | head -1) Started!"
;;
trojan | trojan-go) #client
trojan) #client
gen_config_file $UDP_RELAY_SERVER $type 2 $tmp_udp_local_port
ln_start_bin $(first_type trojan-go trojan) $type --config $udp_config_file
ln_start_bin $(first_type ipt2socks) ipt2socks -U -b 0.0.0.0 -4 -s 127.0.0.1 -p $tmp_udp_local_port -l $tmp_udp_port
echolog "UDP TPROXY Relay:$($(first_type trojan-go trojan) --version 2>&1 | head -1) Started!"
;;
trojan-go)
gen_config_file $UDP_RELAY_SERVER $type 2 $udp_config_file
ln_start_bin $(first_type trojan-go trojan) $type --config $udp_config_file
echolog "UDP TPROXY Relay:$($(first_type trojan-go trojan) --version 2>&1 | head -1) Started!"
;;
naiveproxy)
echolog "NaïveProxy UDP TPROXY Relay not supported!"
redir_udp=0
ARG_UDP=""
;;
socks5)
gen_config_file $UDP_RELAY_SERVER $type 2 $tmp_udp_port
ln_start_bin $(first_type redsocks2) redsocks2 -c $udp_config_file
if [ "$(uci_get_by_name $UDP_RELAY_SERVER auth_enable 0)" == "1" ]; then
local auth="-a $(uci_get_by_name $UDP_RELAY_SERVER username) -k $(uci_get_by_name $UDP_RELAY_SERVER password)"
fi
ln_start_bin $(first_type ipt2socks) ipt2socks $udp_config_file -U -4 -s $(uci_get_by_name $UDP_RELAY_SERVER server) -p $(uci_get_by_name $UDP_RELAY_SERVER server_port) -l $tmp_udp_port $auth
#gen_config_file $UDP_RELAY_SERVER $type 2 $tmp_udp_port
#ln_start_bin $(first_type redsocks2) redsocks2 -c $udp_config_file
echolog "UDP TPROXY Relay:Socks5 REDIRECT/TPROXY Started!"
;;
tun)
@ -371,7 +394,6 @@ start_shunt() {
case "$type" in
ss | ssr)
gen_config_file $SHUNT_SERVER $type 3 $tmp_shunt_port
#gen_config_file $SHUNT_SERVER $type 3 $tmp_local_port
ln_start_bin $(first_type ${type}-redir) ${type}-redir -c $shunt_config_file
if [ -n "$tmp_local_port" ]; then
local tmp_port=$tmp_local_port
@ -418,6 +440,22 @@ start_shunt() {
echolog "shunt:$($(first_type "naive") --version 2>&1 | head -1) Started!"
redir_udp=0
;;
socks5)
if [ "$(uci_get_by_name $SHUNT_SERVER auth_enable 0)" == "1" ]; then
local auth="-a $(uci_get_by_name $SHUNT_SERVER username) -k $(uci_get_by_name $SHUNT_SERVER password)"
fi
ln_start_bin $(first_type ipt2socks) ipt2socks $shunt_config_file -R -4 -s $(uci_get_by_name $SHUNT_SERVER server) -p $(uci_get_by_name $SHUNT_SERVER server_port) -l $tmp_shunt_port $auth
#gen_config_file $SHUNT_SERVER $type 3 $tmp_shunt_port
#ln_start_bin $(first_type redsocks2) redsocks2 -c $shunt_config_file
if [ -n "$tmp_local_port" ]; then
local tmp_port=$tmp_local_port
else
local tmp_port=$tmp_shunt_local_port
ln_start_bin $(first_type microsocks) microsocks -i 127.0.0.1 -p $tmp_port shunt-dns-ssr-plus
fi
ln_start_bin $(first_type dns2socks) dns2socks 127.0.0.1:$tmp_port 8.8.8.8:53 127.0.0.1:$tmp_shunt_dns_port -q
echolog "shunt:$type REDIRECT/TPROXY Started!"
;;
*)
gen_config_file $SHUNT_SERVER $type 3 $tmp_shunt_port
ln_start_bin $(first_type redsocks2) redsocks2 -c $shunt_config_file
@ -445,7 +483,7 @@ start_local() {
echolog "Global_Socks5:$(get_name $type) Started!"
;;
vmess | vless)
if [ "_local" == "1" ]; then
if [ "$_local" == "2" ]; then
gen_config_file $LOCAL_SERVER $type 4 0 $local_port
ln_start_bin $(first_type xray v2ray) v2ray -config $local_config_file
echolog "Global_Socks5:$($(first_type "xray" "v2ray") -version | head -1) Started!"
@ -514,7 +552,7 @@ Start_Run() {
trojan | trojan-go)
gen_config_file $GLOBAL_SERVER $type 1 $tcp_port
ln_start_bin $(first_type trojan-go trojan) $type --config $tcp_config_file
echolog "Main node:$($(first_type $type) --version 2>&1 | head -1) Started!"
echolog "Main node:$($(first_type trojan-go trojan) --version 2>&1 | head -1) Started!"
;;
naiveproxy)
gen_config_file $GLOBAL_SERVER $type 1 $tcp_port
@ -522,10 +560,14 @@ Start_Run() {
echolog "Main node:$($(first_type naive) --version 2>&1 | head -1) , $threads Threads Started!"
;;
socks5)
gen_config_file $GLOBAL_SERVER $type 1 $tcp_port
for i in $(seq 1 $threads); do
ln_start_bin $(first_type redsocks2) redsocks2 -c $tcp_config_file
done
if [ "$(uci_get_by_name $GLOBAL_SERVER auth_enable 0)" == "1" ]; then
local auth="-a $(uci_get_by_name $GLOBAL_SERVER username) -k $(uci_get_by_name $GLOBAL_SERVER password)"
fi
ln_start_bin $(first_type ipt2socks) ipt2socks $tcp_config_file -R -4 -j $threads -s $(uci_get_by_name $GLOBAL_SERVER server) -p $(uci_get_by_name $GLOBAL_SERVER server_port) -l $tcp_port $auth
#gen_config_file $GLOBAL_SERVER $type 1 $tcp_port
#for i in $(seq 1 $threads); do
# ln_start_bin $(first_type redsocks2) redsocks2 -c $tcp_config_file
#done
echolog "Main node:Socks5 REDIRECT/TPROXY $threads Threads Started!"
;;
tun)
@ -729,7 +771,6 @@ start_rules() {
w | W | b | B) local ac_ips="$lan_ac_mode$lan_ac_ips" ;;
esac
fi
#deal gfw firewall rule
gfwmode() {
case "$(uci_get_by_type global run_mode)" in
gfw) echo "-g" ;;
@ -830,7 +871,6 @@ stop() {
ps -w | grep -v "grep" | grep ssr-monitor | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
ps -w | grep -v "grep" | grep "sleep 0000" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
ps -w | grep -v "grep" | grep "$TMP_PATH" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
#killall -q -9 ss-redir ss-local obfs-local ssr-redir ssr-local ssr-server v2ray v2ray-plugin xray trojan naive microsocks ipt2socks dns2socks redsocks2 pdnsd
killall -q -9 v2ray-plugin obfs-local
rm -f /var/lock/ssr-monitor.lock
if [ -f "/var/dnsmasq.d/dnsmasq-ssrplus.conf" ]; then

View File

@ -18,7 +18,7 @@ local Xray = {
sniffing = {enabled = true, destOverride = {"http", "tls"}}
} or nil,
-- 开启 socks 代理
inboundDetour = (proto == "tcp" and socks_port ~= "0") and {
inboundDetour = (proto:find("tcp") and socks_port ~= "0") and {
{
protocol = "socks",
port = tonumber(socks_port),

View File

@ -1,4 +1,4 @@
# Copyright (C) 2020 Openwrt.org
# Copyright (C) 2021 Openwrt.org
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
@ -10,8 +10,8 @@ LUCI_DEPENDS:=+uugamebooster
LUCI_PKGARCH:=all
PKG_NAME:=luci-app-uugamebooster
PKG_VERSION:=1.0
PKG_RELEASE:=5
PKG_RELEASE:=7
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature
# call BuildPackage - OpenWrt buildroot signature

View File

@ -1,15 +0,0 @@
module("luci.controller.uugamebooster",package.seeall)
function index()
if not nixio.fs.access("/etc/config/uugamebooster") then return end
entry({"admin", "services", "uugamebooster"}, cbi("uugamebooster/uugamebooster"), ("UU Game Booster"),99).dependent=true
entry({"admin","services","uugamebooster","status"},call("act_status")).leaf=true
end
function act_status()
local e={}
e.running=luci.sys.call("pgrep -f uugamebooster >/dev/null")==0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end

View File

@ -0,0 +1,15 @@
module("luci.controller.uuplugin",package.seeall)
function index()
if not nixio.fs.access("/etc/config/uuplugin") then return end
entry({"admin", "services", "uuplugin"}, cbi("uuplugin/uuplugin"), ("UU GameAcc"),99).dependent=true
entry({"admin","services","uuplugin","status"},call("act_status")).leaf=true
end
function act_status()
local e={}
e.running=luci.sys.call("pgrep -f uuplugin >/dev/null")==0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end

View File

@ -1,24 +0,0 @@
require("luci.util")
mp = Map("uugamebooster", translate("UU Game Booster"))
mp.description = translate("A Paid Game Acceleration service")
mp:section(SimpleSection).template = "uugamebooster/uugamebooster_status"
s = mp:section(TypedSection, "uugamebooster")
s.anonymous=true
s.addremove=false
o = s:option(Flag, "enabled", translate("Enable"))
o.default = 0
o.optional = false
function o.write(self, section, value)
if value == "1" then
luci.sys.call("/etc/init.d/uugamebooster start >/dev/null && /etc/init.d/uugamebooster enable >/dev/null")
else
luci.sys.call("/etc/init.d/uugamebooster stop >/dev/null && /etc/init.d/uugamebooster disable >/dev/null")
end
return Flag.write(self, section, value)
end
return mp

View File

@ -0,0 +1,17 @@
require("luci.util")
mp = Map("uuplugin", translate("UU Game Accelerator"))
mp.description = translate("A Paid Game Acceleration service")
mp:section(SimpleSection).template = "uuplugin/uuplugin_status"
s = mp:section(TypedSection, "uuplugin")
s.anonymous=true
s.addremove=false
o = s:option(Flag, "enabled", translate("Enable"))
o.default = 0
o.optional = false
mp:section(SimpleSection).template = "uuplugin/uuplugin_qcode"
return mp

View File

@ -1,21 +0,0 @@
<script type="text/javascript">//<![CDATA[
XHR.poll(3, '<%=url([[admin]], [[services]], [[uugamebooster]], [[status]])%>', null,
function(x, data) {
var tb = document.getElementById('uugamebooster_status');
if (data && tb) {
if (data.running) {
tb.innerHTML = '<em><b><font color=green>UU Game Booster <%:RUNNING%></font></b></em>';
} else {
tb.innerHTML = '<em><b><font color=red>UU Game Booster <%:NOT RUNNING%></font></b></em>';
}
}
}
);
//]]>
</script>
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
<fieldset class="cbi-section">
<p id="uugamebooster_status">
<em><%:Collecting data...%></em>
</p>
</fieldset>

View File

@ -0,0 +1,6 @@
<fieldset class="cbi-section">
<p id="uugamebooster_qcode">
<img src="/uuios.png" height="300" /><img src="/uuandriod.png" height="300" />
</p>
</fieldset>

View File

@ -0,0 +1,21 @@
<script type="text/javascript">//<![CDATA[
XHR.poll(3, '<%=url([[admin]], [[services]], [[uuplugin]], [[status]])%>', null,
function(x, data) {
var tb = document.getElementById('uuplugin_status');
if (data && tb) {
if (data.running) {
tb.innerHTML = '<em><b><font color=green>UU GameAcc <%:RUNNING%></font></b></em>';
} else {
tb.innerHTML = '<em><b><font color=red>UU GameAcc <%:NOT RUNNING%></font></b></em>';
}
}
}
);
//]]>
</script>
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
<fieldset class="cbi-section">
<p id="uuplugin_status">
<em><%:Collecting data...%></em>
</p>
</fieldset>

View File

@ -1,9 +0,0 @@
msgid "Enable"
msgstr "启用"
msgid "UU Game Booster"
msgstr "网易UU网游加速器"
msgid "A Paid Game Acceleration service"
msgstr "一个富家子弟用的游戏加速器"

View File

@ -0,0 +1,12 @@
msgid "Enable"
msgstr "启用"
msgid "UU GameAcc"
msgstr "UU游戏加速器"
msgid "UU Game Accelerator"
msgstr "UU游戏加速器"
msgid "A Paid Game Acceleration service"
msgstr "一个富家子弟用的主机游戏加速器 (开启服务后使用手机APP绑定路由器并指定加速主机)"

View File

@ -1,4 +0,0 @@
config uugamebooster 'uugamebooster'
option enabled '0'

View File

@ -0,0 +1,4 @@
config uuplugin 'uuplugin'
option enabled '0'

View File

@ -0,0 +1,23 @@
#!/bin/sh /etc/rc.common
START=99
STOP=10
USE_PROCD=1
NAME="uugamebooster"
UU_BIN="/usr/share/uugamebooster/uuplugin"
UU_CONF="/usr/share/uugamebooster/uu.conf"
UU_LOGFILE="/tmp/uugamebooster.log"
start_service() {
config_load uuplugin
local enable
config_get_bool enable uuplugin enabled
if [ "$enable" -eq 1 ]; then
procd_open_instance
procd_set_param command $UU_BIN $UU_CONF >$UU_LOGFILE 2>&1
procd_set_param respawn
procd_close_instance
fi
}

View File

@ -1,11 +0,0 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@uugamebooster[-1]
add ucitrack uugamebooster
set ucitrack.@uugamebooster[-1].init=uugamebooster
commit ucitrack
EOF
rm -f /tmp/luci-indexcache
exit 0

View File

@ -0,0 +1,11 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@uuplugin[-1]
add ucitrack uuplugin
set ucitrack.@uuplugin[-1].init=uuplugin
commit ucitrack
EOF
rm -f /tmp/luci-indexcache
exit 0

View File

@ -23,18 +23,19 @@ PKG_BUILD_PARALLEL:=1
include $(INCLUDE_DIR)/package.mk
define Package/shadowsocksr-libev
define Package/shadowsocksr-libev/Default
SECTION:=net
CATEGORY:=Network
SUBMENU:=Web Servers/Proxies
TITLE:=Lightweight Secured Socks5 Proxy
URL:=https://github.com/shadowsocksrr/shadowsocksr-libev
DEPENDS:=+libev +libsodium +libopenssl +libpthread +libpcre +libudns +zlib
PROVIDES:=shadowsocksr-libev
endef
Package/shadowsocksr-libev-server = $(Package/shadowsocksr-libev)
Package/shadowsocksr-libev-alt = $(Package/shadowsocksr-libev)
Package/shadowsocksr-libev-ssr-local = $(Package/shadowsocksr-libev)
Package/shadowsocksr-libev-server = $(Package/shadowsocksr-libev/Default)
Package/shadowsocksr-libev-alt = $(Package/shadowsocksr-libev/Default)
Package/shadowsocksr-libev-ssr-local = $(Package/shadowsocksr-libev/Default)
CONFIGURE_ARGS += --disable-documentation --disable-ssp --disable-assert \
--enable-system-shared-lib
@ -42,15 +43,6 @@ CONFIGURE_ARGS += --disable-documentation --disable-ssp --disable-assert \
TARGET_CFLAGS += -flto
TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed
define Package/shadowsocksr-libev/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-redir $(1)/usr/bin/ssr-redir
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-local $(1)/usr/bin/ssr-local
$(LN) ssr-local $(1)/usr/bin/ssr-tunnel
$(INSTALL_BIN) $(PKG_BUILD_DIR)/server/ss-check $(1)/usr/bin/ssr-check
$(INSTALL_BIN) $(PKG_BUILD_DIR)/server/ss-server $(1)/usr/bin/ssr-server
endef
define Package/shadowsocksr-libev-alt/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-redir $(1)/usr/bin/ssr-redir
@ -68,7 +60,6 @@ define Package/shadowsocksr-libev-ssr-local/install
$(LN) ssr-local $(1)/usr/bin/ssr-tunnel
endef
$(eval $(call BuildPackage,shadowsocksr-libev))
$(eval $(call BuildPackage,shadowsocksr-libev-alt))
$(eval $(call BuildPackage,shadowsocksr-libev-server))
$(eval $(call BuildPackage,shadowsocksr-libev-ssr-local))

View File

@ -13,7 +13,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=uugamebooster
PKG_VERSION:=v2.7.2
PKG_RELEASE:=6
PKG_RELEASE:=5
include $(INCLUDE_DIR)/package.mk
@ -70,8 +70,8 @@ define Build/Compile
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/uugamebooster.init $(1)/etc/init.d/uugamebooster
# $(INSTALL_DIR) $(1)/etc/init.d
# $(INSTALL_BIN) ./files/uugamebooster.init $(1)/etc/init.d/uuplugin
$(INSTALL_DIR) $(1)/usr/share/$(PKG_NAME)
$(INSTALL_BIN) $(UNTAR_DIR)/uuplugin $(1)/usr/share/$(PKG_NAME)/uuplugin

View File

@ -1,18 +0,0 @@
#!/bin/sh /etc/rc.common
START=99
STOP=10
USE_PROCD=1
NAME="uugamebooster"
UU_BIN="/usr/share/uugamebooster/uuplugin"
UU_CONF="/usr/share/uugamebooster/uu.conf"
UU_LOGFILE="/tmp/uugamebooster.log"
start_service() {
procd_open_instance
procd_set_param command $UU_BIN $UU_CONF >$UU_LOGFILE 2>&1
procd_set_param respawn
procd_close_instance
}

View File

@ -9,13 +9,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=xray
PKG_VERSION:=1.2.2
PKG_VERSION:=1.2.3
PKG_RELEASE:=1
PKG_BUILD_DIR:=$(BUILD_DIR)/Xray-core-$(PKG_VERSION)
PKG_SOURCE:=xray-core-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/XTLS/xray-core/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=b9b38bc69e660d3a6d0545efea4d0891ee81a2d55c83a6fa893cbd680a071023
PKG_HASH:=1deed281d2b976c0132b57194a09b62a1b978ec1b35d8329894b80f8d47befb7
PKG_LICENSE:=MPL
PKG_LICENSE_FILES:=LICENSE
@ -79,7 +79,6 @@ endef
ifeq ($(CONFIG_XRAY_COMPRESS_GOPROXY),y)
export GO111MODULE=on
export GOPROXY=https://goproxy.io
#export GOPROXY=https://mirrors.aliyun.com/goproxy/
endif
GEOIP_VER:=latest

View File

@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall
PKG_VERSION:=4
PKG_RELEASE:=7
PKG_DATE:=20210111
PKG_RELEASE:=10
PKG_DATE:=20210122
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
@ -69,10 +69,6 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS_NG
bool "Include ChinaDNS-NG"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_https_dns_proxy
bool "Include Https DNS Proxy(DoH)"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_dns2socks
bool "Include dns2socks"
default n
@ -96,7 +92,6 @@ define Package/$(PKG_NAME)
DEPENDS:=+libmbedtls +iptables-mod-tproxy +ip +ipset +coreutils +coreutils-base64 +coreutils-nohup +luci-lib-jsonc \
+curl +ca-certificates +resolveip +unzip +dnsmasq-full +tcping +libuci-lua \
+ipt2socks \
+ssocks \
+microsocks \
+pdnsd-alt \
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks:shadowsocks-libev-ss-redir \
@ -106,7 +101,6 @@ define Package/$(PKG_NAME)
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR:shadowsocksr-libev-ssr-local \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server:shadowsocksr-libev-server \
+PACKAGE_$(PKG_NAME)_INCLUDE_Xray:xray \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Plus:trojan-plus \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_GO:trojan-go \
+PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy:naiveproxy \
@ -114,7 +108,6 @@ define Package/$(PKG_NAME)
+PACKAGE_$(PKG_NAME)_INCLUDE_kcptun:kcptun-client \
+PACKAGE_$(PKG_NAME)_INCLUDE_haproxy:haproxy \
+PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS_NG:chinadns-ng \
+PACKAGE_$(PKG_NAME)_INCLUDE_https_dns_proxy:https-dns-proxy \
+PACKAGE_$(PKG_NAME)_INCLUDE_dns2socks:dns2socks \
+PACKAGE_$(PKG_NAME)_INCLUDE_v2ray-plugin:v2ray-plugin \
+PACKAGE_$(PKG_NAME)_INCLUDE_simple-obfs:simple-obfs

View File

@ -9,7 +9,6 @@ local api = require "luci.model.cbi.passwall.api.api"
local kcptun = require "luci.model.cbi.passwall.api.kcptun"
local brook = require "luci.model.cbi.passwall.api.brook"
local xray = require "luci.model.cbi.passwall.api.xray"
local v2ray = require "luci.model.cbi.passwall.api.v2ray"
local trojan_go = require "luci.model.cbi.passwall.api.trojan_go"
function index()
@ -72,8 +71,6 @@ function index()
entry({"admin", "services", appname, "brook_update"}, call("brook_update")).leaf = true
entry({"admin", "services", appname, "xray_check"}, call("xray_check")).leaf = true
entry({"admin", "services", appname, "xray_update"}, call("xray_update")).leaf = true
entry({"admin", "services", appname, "v2ray_check"}, call("v2ray_check")).leaf = true
entry({"admin", "services", appname, "v2ray_update"}, call("v2ray_update")).leaf = true
entry({"admin", "services", appname, "trojan_go_check"}, call("trojan_go_check")).leaf = true
entry({"admin", "services", appname, "trojan_go_update"}, call("trojan_go_update")).leaf = true
end
@ -191,12 +188,12 @@ function socks_status()
local index = luci.http.formvalue("index")
local id = luci.http.formvalue("id")
e.index = index
e.socks_status = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/' | grep 'SOCKS_%s' > /dev/null", appname, id)) == 0
e.socks_status = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/' | grep '%s' | grep 'SOCKS_' > /dev/null", appname, id)) == 0
local use_http = ucic:get(appname, id, "http_port") or 0
e.use_http = 0
if tonumber(use_http) > 0 then
e.use_http = 1
e.http_status = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/' | grep 'SOCKS2HTTP_%s' > /dev/null", appname, id)) == 0
e.http_status = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/' | grep '%s' | grep -E 'HTTP_|HTTP2SOCKS' > /dev/null", appname, id)) == 0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
@ -413,25 +410,6 @@ function xray_update()
http_write_json(json)
end
function v2ray_check()
local json = v2ray.to_check("")
http_write_json(json)
end
function v2ray_update()
local json = nil
local task = http.formvalue("task")
if task == "extract" then
json = v2ray.to_extract(http.formvalue("file"), http.formvalue("subfix"))
elseif task == "move" then
json = v2ray.to_move(http.formvalue("file"))
else
json = v2ray.to_download(http.formvalue("url"))
end
http_write_json(json)
end
function trojan_go_check()
local json = trojan_go.to_check("")
http_write_json(json)

View File

@ -149,31 +149,6 @@ function get_xray_version(file)
return ""
end
function get_v2ray_path()
local path = uci_get_type("global_app", "v2ray_file")
return path
end
function get_v2ray_version(file)
if file == nil then file = get_v2ray_path() end
chmod_755(file)
if fs.access(file) then
if file == get_v2ray_path() then
local md5 = sys.exec("echo -n $(md5sum " .. file .. " | awk '{print $1}')")
if fs.access("/tmp/psw_" .. md5) then
return sys.exec("cat /tmp/psw_" .. md5)
else
local version = sys.exec("echo -n $(%s -version | awk '{print $2}' | sed -n 1P)" % file)
sys.call("echo '" .. version .. "' > " .. "/tmp/psw_" .. md5)
return version
end
else
return sys.exec("echo -n $(%s -version | awk '{print $2}' | sed -n 1P)" % file)
end
end
return ""
end
function get_trojan_go_path()
local path = uci_get_type("global_app", "trojan_go_file")
return path

View File

@ -1,15 +1,8 @@
module("luci.model.cbi.passwall.api.gen_xray", package.seeall)
local api = require "luci.model.cbi.passwall.api.api"
local ucursor = require"luci.model.uci".cursor()
local sys = require "luci.sys"
local json = require "luci.jsonc"
local appname = "passwall"
local inbounds = {}
local outbounds = {}
local routing = nil
local myarg = {
"-node", "-proto", "-redir_port", "-socks_proxy_port", "-loglevel"
"-node", "-proto", "-redir_port", "-socks_proxy_port", "-http_proxy_port", "-dns_listen_port", "-dns_server", "-doh_url", "-doh_host", "-doh_socks_address", "-doh_socks_port", "-loglevel"
}
local var = api.get_args(arg, myarg)
@ -18,10 +11,26 @@ local node_section = var["-node"]
local proto = var["-proto"]
local redir_port = var["-redir_port"]
local socks_proxy_port = var["-socks_proxy_port"]
local http_proxy_port = var["-http_proxy_port"]
local dns_listen_port = var["-dns_listen_port"]
local dns_server = var["-dns_server"]
local doh_url = var["-doh_url"]
local doh_host = var["-doh_host"]
local doh_socks_address = var["-doh_socks_address"]
local doh_socks_port = var["-doh_socks_port"]
local loglevel = var["-loglevel"] or "warning"
local network = proto
local new_port
local ucursor = require"luci.model.uci".cursor()
local sys = require "luci.sys"
local json = require "luci.jsonc"
local appname = "passwall"
local dns = nil
local inbounds = {}
local outbounds = {}
local routing = nil
local function get_new_port()
if new_port then
new_port = tonumber(sys.exec(string.format("echo -n $(/usr/share/%s/app.sh get_new_port %s tcp)", appname, new_port + 1)))
@ -48,13 +57,13 @@ function gen_outbound(node, tag, relay_port)
node.port = new_port
sys.call(string.format('/usr/share/%s/app.sh run_socks "%s" "%s" "%s" "%s" "%s" "%s" "%s" "%s"> /dev/null',
appname,
new_port,
node_id,
"127.0.0.1",
new_port,
string.format("/var/etc/%s/v2_%s_%s.json", appname, node_type, node_id),
"0",
"nil",
"4",
relay_port and tostring(relay_port) or ""
)
)
@ -142,7 +151,7 @@ function gen_outbound(node, tag, relay_port)
{
id = node.uuid,
alterId = tonumber(node.alter_id),
level = node.level and tonumber(node.level) or 0,
level = 0,
security = (node.protocol == "vmess") and node.security or nil,
encryption = node.encryption or "none",
flow = node.flow or nil
@ -178,6 +187,14 @@ if node_section then
})
network = "tcp,udp"
end
if http_proxy_port then
table.insert(inbounds, {
listen = "0.0.0.0",
port = tonumber(http_proxy_port),
protocol = "http",
settings = {allowTransparent = false}
})
end
if redir_port then
table.insert(inbounds, {
@ -269,6 +286,38 @@ if node_section then
local default_node_id = node.default_node or nil
if default_node_id and default_node_id ~= "nil" then
local default_node = ucursor:get_all(appname, default_node_id)
if "1" == node.default_proxy then
local node_id = node.main_node or nil
if node_id and node_id ~= "nil" then
if node_id == default_node_id then
else
new_port = get_new_port()
table.insert(inbounds, {
tag = "proxy_default",
listen = "127.0.0.1",
port = new_port,
protocol = "dokodemo-door",
settings = {network = "tcp,udp", address = default_node.address, port = tonumber(default_node.port)}
})
if default_node.tls_serverName == nil then
default_node.tls_serverName = default_node.address
end
default_node.address = "127.0.0.1"
default_node.port = new_port
local node = ucursor:get_all(appname, node_id)
local outbound = gen_outbound(node, "main")
if outbound then
table.insert(outbounds, outbound)
local rule = {
type = "field",
inboundTag = {"proxy_default"},
outboundTag = "main"
}
table.insert(rules, rule)
end
end
end
end
local default_outbound = gen_outbound(default_node, "default")
if default_outbound then
table.insert(outbounds, default_outbound)
@ -307,21 +356,132 @@ if node_section then
local outbound = gen_outbound(node)
if outbound then table.insert(outbounds, outbound) end
end
end
-- 额外传出连接
table.insert(outbounds, {protocol = "freedom", tag = "direct", settings = {keep = ""}})
if dns_server then
local rules = {}
dns = {
tag = "dns-in1",
servers = {
dns_server
}
}
if doh_url and doh_host then
dns.hosts = {
[doh_host] = dns_server
}
dns.servers = {
doh_url
}
end
if dns_listen_port then
table.insert(inbounds, {
listen = "127.0.0.1",
port = tonumber(dns_listen_port),
protocol = "dokodemo-door",
tag = "dns-in",
settings = {
address = dns_server,
port = 53,
network = "udp"
}
})
table.insert(outbounds, {
protocol = "dns",
tag = "dns-out"
})
end
table.insert(rules, {
type = "field",
inboundTag = {
"dns-in"
},
outboundTag = "dns-out"
})
if doh_socks_address and doh_socks_port then
table.insert(outbounds, {
tag = "out",
protocol = "socks",
streamSettings = {
network = "tcp",
security = "none"
},
settings = {
servers = {
{
address = doh_socks_address,
port = tonumber(doh_socks_port)
}
}
}
})
table.insert(rules, {
type = "field",
inboundTag = {
"dns-in1"
},
outboundTag = "out"
})
else
table.insert(rules, {
type = "field",
inboundTag = {
"dns-in1"
},
outboundTag = "direct"
})
end
routing = {
domainStrategy = "IPOnDemand",
rules = rules
}
end
if inbounds or outbounds then
table.insert(outbounds, {
protocol = "freedom",
tag = "direct",
settings = {domainStrategy = "UseIPv4"}
})
local xray = {
log = {
-- error = string.format("/var/etc/passwall/%s.log", node[".name"]),
loglevel = loglevel
},
-- DNS
dns = dns,
-- 传入连接
inbounds = inbounds,
-- 传出连接
outbounds = outbounds,
-- 路由
routing = routing
routing = routing,
-- 本地策略
--[[
policy = {
levels = {
[0] = {
handshake = 4,
connIdle = 300,
uplinkOnly = 2,
downlinkOnly = 5,
bufferSize = 10240,
statsUserUplink = false,
statsUserDownlink = false
}
},
system = {
statsInboundUplink = false,
statsInboundDownlink = false
}
}
]]--
}
print(json.stringify(xray, 1))
end

View File

@ -1,173 +0,0 @@
module("luci.model.cbi.passwall.api.v2ray", package.seeall)
local fs = require "nixio.fs"
local sys = require "luci.sys"
local util = require "luci.util"
local i18n = require "luci.i18n"
local api = require "luci.model.cbi.passwall.api.api"
local v2ray_api = "https://api.github.com/repos/v2fly/v2ray-core/releases/latest"
local is_armv7 = false
function to_check(arch)
local app_path = api.get_v2ray_path() or ""
if app_path == "" then
return {
code = 1,
error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "V2ray")
}
end
if not arch or arch == "" then arch = api.auto_get_arch() end
local file_tree, sub_version = api.get_file_info(arch)
if sub_version == "7" then is_armv7 = true end
if file_tree == "" then
return {
code = 1,
error = i18n.translate("Can't determine ARCH, or ARCH not supported.")
}
end
if file_tree == "amd64" then file_tree = "64" end
if file_tree == "386" then file_tree = "32" end
local json = api.get_api_json(v2ray_api)
if json.tag_name == nil then
return {
code = 1,
error = i18n.translate("Get remote version info failed.")
}
end
local now_version = api.get_v2ray_version()
local remote_version = json.tag_name:match("[^v]+")
local needs_update = api.compare_versions(now_version, "<", remote_version)
local html_url, download_url
if needs_update then
html_url = json.html_url
for _, v in ipairs(json.assets) do
if v.name and v.name:match("linux%-" .. file_tree) then
download_url = v.browser_download_url
break
end
end
end
if needs_update and not download_url then
return {
code = 1,
now_version = now_version,
version = remote_version,
html_url = html_url,
error = i18n.translate("New version found, but failed to get new version download url.")
}
end
return {
code = 0,
update = needs_update,
now_version = now_version,
version = remote_version,
url = {html = html_url, download = download_url}
}
end
function to_download(url)
local app_path = api.get_v2ray_path() or ""
if app_path == "" then
return {
code = 1,
error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "V2ray")
}
end
if not url or url == "" then
return {code = 1, error = i18n.translate("Download url is required.")}
end
sys.call("/bin/rm -f /tmp/v2ray_download.*")
local tmp_file = util.trim(util.exec("mktemp -u -t v2ray_download.XXXXXX"))
local result = api.exec(api.curl, {api._unpack(api.curl_args), "-o", tmp_file, url}, nil, api.command_timeout) == 0
if not result then
api.exec("/bin/rm", {"-f", tmp_file})
return {
code = 1,
error = i18n.translatef("File download failed or timed out: %s", url)
}
end
return {code = 0, file = tmp_file}
end
function to_extract(file, subfix)
local app_path = api.get_v2ray_path() or ""
if app_path == "" then
return {
code = 1,
error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "V2ray")
}
end
if not file or file == "" or not fs.access(file) then
return {code = 1, error = i18n.translate("File path required.")}
end
if sys.exec("echo -n $(opkg list-installed | grep -c unzip)") ~= "1" then
api.exec("/bin/rm", {"-f", file})
return {
code = 1,
error = i18n.translate("Not installed unzip, Can't unzip!")
}
end
sys.call("/bin/rm -rf /tmp/v2ray_extract.*")
local tmp_dir = util.trim(util.exec("mktemp -d -t v2ray_extract.XXXXXX"))
local output = {}
api.exec("/usr/bin/unzip", {"-o", file, "-d", tmp_dir},
function(chunk) output[#output + 1] = chunk end)
local files = util.split(table.concat(output))
api.exec("/bin/rm", {"-f", file})
return {code = 0, file = tmp_dir}
end
function to_move(file)
local app_path = api.get_v2ray_path() or ""
if app_path == "" then
return {
code = 1,
error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "V2ray")
}
end
if not file or file == "" then
sys.call("/bin/rm -rf /tmp/v2ray_extract.*")
return {code = 1, error = i18n.translate("Client file is required.")}
end
if not arch or arch == "" then arch = api.auto_get_arch() end
local file_tree, sub_version = api.get_file_info(arch)
local t = ""
sys.call("/etc/init.d/passwall stop")
local result = nil
if sub_version and sub_version == "7" then t = "_armv7" end
result = api.exec("/bin/mv", { "-f", file .. "/v2ray" .. t, app_path }, nil, api.command_timeout) == 0
sys.call("/bin/rm -rf /tmp/v2ray_extract.*")
if not result or not fs.access(app_path) then
return {
code = 1,
error = i18n.translatef("Can't move new file to path: %s", app_path)
}
end
api.chmod_755(app_path)
sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &")
return {code = 0}
end

View File

@ -10,7 +10,6 @@ s = m:section(TypedSection, "global_app", translate("App Update"),
"</font>")
s.anonymous = true
s:append(Template(appname .. "/app_update/xray_version"))
s:append(Template(appname .. "/app_update/v2ray_version"))
s:append(Template(appname .. "/app_update/trojan_go_version"))
s:append(Template(appname .. "/app_update/kcptun_version"))
s:append(Template(appname .. "/app_update/brook_version"))
@ -19,10 +18,6 @@ o = s:option(Value, "xray_file", translatef("%s App Path", "Xray"))
o.default = "/usr/bin/xray"
o.rmempty = false
o = s:option(Value, "v2ray_file", translatef("%s App Path", "V2ray"))
o.default = "/usr/bin/v2ray"
o.rmempty = false
o = s:option(Value, "trojan_go_file", translatef("%s App Path", "Trojan-Go"))
o.default = "/usr/bin/trojan-go"
o.rmempty = false

View File

@ -2,16 +2,27 @@ local d = require "luci.dispatcher"
local uci = require"luci.model.uci".cursor()
local api = require "luci.model.cbi.passwall.api.api"
local appname = "passwall"
local has_xray = api.is_finded("xray")
m = Map(appname)
local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do
nodes_table[#nodes_table + 1] = {
id = e[".name"],
remarks = e.remarks_name
remarks = e.remarks_name,
type = e["type"]
}
end
local socks_table = {}
if tonumber(m:get("@global[0]", "tcp_node_socks") or 0) == 1 then
local id = "127.0.0.1" .. ":" .. m:get("@global[0]", "tcp_node_socks_port")
socks_table[#socks_table + 1] = {
id = id,
remarks = id .. " - " .. translate("TCP Node")
}
end
uci:foreach(appname, "socks", function(s)
if s.enabled == "1" and s.node then
local id, remarks
@ -25,7 +36,7 @@ uci:foreach(appname, "socks", function(s)
end
end
end
id = "0.0.0.0" .. ":" .. s.port
id = "127.0.0.1" .. ":" .. s.port
socks_table[#socks_table + 1] = {
id = id,
remarks = id .. " - " .. (remarks or translate("Misconfigured"))
@ -55,7 +66,6 @@ local doh_validate = function(self, value, t)
return nil, translate("DoH request address") .. " " .. translate("Format must be:") .. " URL,IP"
end
m = Map(appname)
local status = m:get("@global_other[0]", "status") or ""
if status:find("big_icon") then
m:append(Template(appname .. "/global/status"))
@ -74,11 +84,11 @@ o = s:taboption("Main", Flag, "enabled", translate("Main switch"))
o.rmempty = false
---- TCP Node
o = s:taboption("Main", ListValue, "tcp_node", translate("TCP Node"))
o.title = translate("TCP Node")
o.description = ""
--o.description = translate("For proxy specific list.")
--o.description = o.description .. "<br />"
tcp_node = s:taboption("Main", ListValue, "tcp_node", translate("TCP Node"))
tcp_node.title = translate("TCP Node")
tcp_node.description = ""
--tcp_node.description = translate("For proxy specific list.")
--tcp_node.description = o.description .. "<br />"
local current_node = luci.sys.exec(string.format("[ -f '/var/etc/%s/id/TCP' ] && echo -n $(cat /var/etc/%s/id/TCP)", appname, appname))
if current_node and current_node ~= "" and current_node ~= "nil" then
local n = uci:get_all(appname, current_node)
@ -86,7 +96,7 @@ if current_node and current_node ~= "" and current_node ~= "nil" then
if tonumber(m:get("@auto_switch[0]", "enable") or 0) == 1 then
local remarks = api.get_full_node_remarks(n)
local url = d.build_url("admin", "services", appname, "node_config", current_node)
o.description = o.description .. translatef("Current node: %s", string.format('<a href="%s">%s</a>', url, remarks)) .. "<br />"
tcp_node.description = tcp_node.description .. translatef("Current node: %s", string.format('<a href="%s">%s</a>', url, remarks)) .. "<br />"
end
if n.protocol and n.protocol == "_shunt" then
uci:foreach(appname, "shunt_rules", function(e)
@ -95,7 +105,7 @@ if current_node and current_node ~= "" and current_node ~= "nil" then
if n[id] and n[id] ~= "nil" then
local url = d.build_url("admin", "services", appname, "node_config", n[id])
local r = api.get_full_node_remarks(uci:get_all(appname, n[id]))
o.description = o.description .. remarks .. "" .. string.format('<a href="%s">%s</a>', url, r) .. "<br />"
tcp_node.description = tcp_node.description .. remarks .. "" .. string.format('<a href="%s">%s</a>', url, r) .. "<br />"
end
end)
local id = "default_node"
@ -103,22 +113,32 @@ if current_node and current_node ~= "" and current_node ~= "nil" then
if n[id] and n[id] ~= "nil" then
local url = d.build_url("admin", "services", appname, "node_config", n[id])
local r = api.get_full_node_remarks(uci:get_all(appname, n[id]))
o.description = o.description .. remarks .. "" .. string.format('<a href="%s">%s</a>', url, r) .. "<br />"
tcp_node.description = tcp_node.description .. remarks .. "" .. string.format('<a href="%s">%s</a>', url, r) .. "<br />"
end
end
end
end
o:value("nil", translate("Close"))
for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end
tcp_node:value("nil", translate("Close"))
o = s:taboption("Main", ListValue, "udp_node", translate("UDP Node"))
o:value("nil", translate("Close"))
o.title = translate("UDP Node")
--o.description = translate("For proxy game network, DNS hijack etc.") .. "<br />" .. translate("The selected server will not use Kcptun.")
o:value("tcp_", translate("Same as the tcp node"))
--o:value("tcp", translate("Same as the tcp node"))
--o:value("tcp_", translate("Same as the tcp node") .. "" .. translate("New process") .. "")
for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end
udp_node = s:taboption("Main", ListValue, "udp_node", translate("UDP Node"))
udp_node:value("nil", translate("Close"))
udp_node.title = translate("UDP Node")
--udp_node.description = translate("For proxy game network, DNS hijack etc.") .. "<br />" .. translate("The selected server will not use Kcptun.")
udp_node:value("tcp_", translate("Same as the tcp node"))
--udp_node:value("tcp", translate("Same as the tcp node"))
--udp_node:value("tcp_", translate("Same as the tcp node") .. "" .. translate("New process") .. "")
tcp_node_socks = s:taboption("Main", Flag, "tcp_node_socks", translate("Enable") .. translate("TCP Node") .. "Socks")
o = s:taboption("Main", Value, "tcp_node_socks_port", "Socks" .. translate("Listen Port"))
o.default = 1080
o.datatype = "port"
o:depends("tcp_node_socks", true)
tcp_node_http = s:taboption("Main", Flag, "tcp_node_http", translate("Enable") .. translate("TCP Node") .. "Http")
o = s:taboption("Main", Value, "tcp_node_http_port", "HTTP" .. translate("Listen Port"))
o.default = 1180
o.datatype = "port"
o:depends("tcp_node_http", true)
s:tab("DNS", translate("DNS"))
@ -131,12 +151,12 @@ if api.is_finded("chinadns-ng") then
o:depends("chinadns_ng", "1")
end
o = s:taboption("DNS", Value, "up_china_dns", translate("Resolver For Local/WhiteList Domains") .. "(UDP)")
o = s:taboption("DNS", Value, "up_china_dns", translate("Local DNS") .. "(UDP)")
o.description = translate("IP:Port mode acceptable, multi value split with english comma.") .. "<br />" .. translate("When the selection is not the default, this DNS is forced to be set to dnsmasq upstream DNS.")
o.default = "default"
o:value("default", translate("Default"))
if api.is_finded("https-dns-proxy") then
o:value("https-dns-proxy", "https-dns-proxy(DoH)")
if has_xray then
o:value("xray_doh", "Xray DNS(DoH)")
end
o:value("223.5.5.5", "223.5.5.5 (" .. translate("Ali") .. "DNS)")
o:value("223.6.6.6", "223.6.6.6 (" .. translate("Ali") .. "DNS)")
@ -150,24 +170,24 @@ o:value("180.76.76.76", "180.76.76.76 (" .. translate("Baidu") .. "DNS)")
---- DoH
o = s:taboption("DNS", Value, "up_china_dns_doh", translate("DoH request address"))
o:value("https://dns.alidns.com/dns-query,223.5.5.5,223.6.6.6", "AliDNS")
o:value("https://doh.pub/dns-query,119.29.29.29,119.28.28.28", "DNSPod")
o.default = "https://dns.alidns.com/dns-query,223.5.5.5,223.6.6.6"
o:value("https://dns.alidns.com/dns-query,223.5.5.5", "AliDNS")
o:value("https://doh.pub/dns-query,119.29.29.29", "DNSPod")
o.default = "https://dns.alidns.com/dns-query,223.5.5.5"
o.validate = doh_validate
o:depends("up_china_dns", "https-dns-proxy")
o:depends("up_china_dns", "xray_doh")
---- DNS Forward Mode
o = s:taboption("DNS", ListValue, "dns_mode", translate("Filter Mode"))
o.rmempty = false
o:reset_values()
if api.is_finded("pdnsd") then
o:value("pdnsd", "pdnsd")
o:value("pdnsd", "pdnsd " .. translatef("Requery DNS By %s", translate("TCP Node")))
end
if api.is_finded("dns2socks") then
o:value("dns2socks", "dns2socks")
end
if api.is_finded("https-dns-proxy") then
o:value("https-dns-proxy", "https-dns-proxy(DoH)")
if has_xray then
o:value("xray_doh", "Xray DNS(DoH)")
end
o:value("udp", translatef("Requery DNS By %s", translate("UDP Node")))
o:value("nonuse", translate("No Filter"))
@ -185,17 +205,10 @@ o.validate = function(self, value, t)
end
o:depends({dns_mode = "custom"})
o = s:taboption("DNS", ListValue, "up_trust_pdnsd_dns", translate("Resolver For The List Proxied"))
-- o.description = translate("You can use other resolving DNS services as trusted DNS, Example: dns2socks, dns-forwarder... 127.0.0.1#5353<br />Only use two at most, english comma separation, If you do not fill in the # and the following port, you are using port 53.")
o.default = "tcp"
o:value("tcp", translatef("Requery DNS By %s", translate("TCP Node")))
o:value("udp", translatef("Requery DNS By %s", translate("UDP Node")))
o:depends("dns_mode", "pdnsd")
o = s:taboption("DNS", ListValue, "up_trust_doh_dns", translate("Resolver For The List Proxied"))
o:value("tcp", translatef("Requery DNS By %s", translate("TCP Node")))
o:value("socks", translatef("Requery DNS By %s", translate("Socks Node")))
o:depends("dns_mode", "https-dns-proxy")
o:depends("dns_mode", "xray_doh")
o = s:taboption("DNS", Value, "socks_server", translate("Socks Server"), translate("Make sure socks service is available on this address."))
for k, v in pairs(socks_table) do o:value(v.id, v.remarks) end
@ -206,27 +219,28 @@ o.validate = function(self, value, t)
return value
end
o:depends({dns_mode = "dns2socks"})
o:depends({dns_mode = "https-dns-proxy", up_trust_doh_dns = "socks"})
o:depends({dns_mode = "xray_doh", up_trust_doh_dns = "socks"})
---- DoH
o = s:taboption("DNS", Value, "up_trust_doh", translate("DoH request address"))
o:value("https://dns.adguard.com/dns-query,176.103.130.130,176.103.130.131", "AdGuard")
o:value("https://cloudflare-dns.com/dns-query,1.1.1.1,1.0.0.1", "Cloudflare")
o:value("https://security.cloudflare-dns.com/dns-query,1.1.1.2,1.0.0.2", "Cloudflare-Security")
o:value("https://doh.opendns.com/dns-query,208.67.222.222,208.67.220.220", "OpenDNS")
o:value("https://dns.google/dns-query,8.8.8.8,8.8.4.4", "Google")
o:value("https://dns.adguard.com/dns-query,176.103.130.130", "AdGuard")
o:value("https://cloudflare-dns.com/dns-query,1.1.1.1", "Cloudflare")
o:value("https://security.cloudflare-dns.com/dns-query,1.1.1.2", "Cloudflare-Security")
o:value("https://doh.opendns.com/dns-query,208.67.222.222", "OpenDNS")
o:value("https://dns.google/dns-query,8.8.8.8", "Google")
o:value("https://doh.libredns.gr/dns-query,116.202.176.26", "LibreDNS")
o:value("https://doh.libredns.gr/ads,116.202.176.26", "LibreDNS (No Ads)")
o:value("https://dns.quad9.net/dns-query,9.9.9.9,149.112.112.112", "Quad9-Recommended")
o.default = "https://dns.google/dns-query,8.8.8.8,8.8.4.4"
o:value("https://dns.quad9.net/dns-query,9.9.9.9", "Quad9-Recommended")
o.default = "https://dns.google/dns-query,8.8.8.8"
o.validate = doh_validate
o:depends({dns_mode = "https-dns-proxy"})
o:depends({dns_mode = "xray_doh"})
---- DNS Forward
o = s:taboption("DNS", Value, "dns_forward", translate("Filtered DNS(For Proxied Domains)"), translate("IP:Port mode acceptable, the 1st for 'dns2socks' if split with english comma."))
o.default = "8.8.4.4"
o:value("8.8.4.4", "8.8.4.4 (Google DNS)")
o = s:taboption("DNS", Value, "dns_forward", translate("Remote DNS"))
--o.description = translate("IP:Port mode acceptable, multi value split with english comma.") .. " " .. translate("If you use dns2socks, only the first one is valid.")
o.default = "8.8.8.8"
o:value("8.8.8.8", "8.8.8.8 (Google DNS)")
o:value("8.8.4.4", "8.8.4.4 (Google DNS)")
o:value("208.67.222.222", "208.67.222.222 (Open DNS)")
o:value("208.67.220.220", "208.67.220.220 (Open DNS)")
o:depends({dns_mode = "dns2socks"})
@ -240,9 +254,6 @@ o:depends({dns_mode = "dns2socks"})
o:depends({dns_mode = "pdnsd"})
]]--
o = s:taboption("DNS", Flag, "use_chnlist", translate("Use ChinaList"), translate("Only useful in non-gfwlist mode.") .. "<br />" .. translate("When used, the domestic DNS will be used only when the chnlist rule is hit, and the domain name that misses the rule will be resolved by remote DNS."))
o.default = "0"
o = s:taboption("DNS", Button, "clear_ipset", translate("Clear IPSET"), translate("Try this feature if the rule modification does not take effect."))
o.inputstyle = "remove"
function o.write(e, e)
@ -344,21 +355,35 @@ o = s:option(Flag, "enabled", translate("Enable"))
o.default = 1
o.rmempty = false
o = s:option(ListValue, "node", translate("Socks Node"))
o:value("tcp", translate("Same as the tcp node"))
for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end
socks_node = s:option(ListValue, "node", translate("Socks Node"))
o = s:option(Value, "port", "Socks" .. translate("Listen Port"))
o.default = 9050
o.datatype = "port"
o.rmempty = false
if api.is_finded("xray") or api.is_finded("v2ray") then
if has_xray then
o = s:option(Value, "http_port", "HTTP" .. translate("Listen Port") .. " " .. translate("0 is not use"))
o.default = 0
o.datatype = "port"
end
for k, v in pairs(nodes_table) do
tcp_node:value(v.id, v.remarks)
tcp_node_socks:depends("tcp_node", v.id)
if has_xray then
tcp_node_http:depends("tcp_node", v.id)
end
udp_node:value(v.id, v.remarks)
if v.type == "Socks" then
if has_xray then
socks_node:value(v.id, v.remarks)
end
else
socks_node:value(v.id, v.remarks)
end
end
m:append(Template(appname .. "/global/footer"))
--[[

View File

@ -83,9 +83,6 @@ if api.is_finded("xray") then
type:value("Xray", translate("Xray"))
type.description = translate("Xray is currently directly compatible with V2ray and used.")
end
if api.is_finded("v2ray") then
type:value("V2ray", translate("V2ray"))
end
if api.is_finded("brook") then
type:value("Brook", translate("Brook"))
end
@ -113,7 +110,6 @@ protocol:value("shadowsocks", translate("Shadowsocks"))
protocol:value("trojan", translate("Trojan"))
protocol:value("_balancing", translate("Balancing"))
protocol:value("_shunt", translate("Shunt"))
protocol:depends("type", "V2ray")
protocol:depends("type", "Xray")
local nodes_table = {}
@ -155,6 +151,14 @@ default_node:value("nil", translate("Close"))
for k, v in pairs(nodes_table) do default_node:value(v.id, v.remarks) end
default_node:depends("protocol", "_shunt")
default_proxy = s:option(Flag, "default_proxy", translate("Default") .. translate("Node") .. translate("Preproxy"), translate("Use the under node for the transit."))
default_proxy.default = 0
default_proxy:depends("protocol", "_shunt")
o = s:option(ListValue, "main_node", " ")
for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end
o:depends("default_proxy", "1")
domainStrategy = s:option(ListValue, "domainStrategy", translate("Domain Strategy"))
domainStrategy:value("AsIs")
domainStrategy:value("IPIfNonMatch")
@ -209,12 +213,6 @@ address:depends({ type = "Xray", protocol = "http" })
address:depends({ type = "Xray", protocol = "socks" })
address:depends({ type = "Xray", protocol = "shadowsocks" })
address:depends({ type = "Xray", protocol = "trojan" })
address:depends({ type = "V2ray", protocol = "vmess" })
address:depends({ type = "V2ray", protocol = "vless" })
address:depends({ type = "V2ray", protocol = "http" })
address:depends({ type = "V2ray", protocol = "socks" })
address:depends({ type = "V2ray", protocol = "shadowsocks" })
address:depends({ type = "V2ray", protocol = "trojan" })
--[[
use_ipv6 = s:option(Flag, "use_ipv6", translate("Use IPv6"))
@ -232,12 +230,6 @@ use_ipv6:depends({ type = "Xray", protocol = "http" })
use_ipv6:depends({ type = "Xray", protocol = "socks" })
use_ipv6:depends({ type = "Xray", protocol = "shadowsocks" })
use_ipv6:depends({ type = "Xray", protocol = "trojan" })
use_ipv6:depends({ type = "V2ray", protocol = "vmess" })
use_ipv6:depends({ type = "V2ray", protocol = "vless" })
use_ipv6:depends({ type = "V2ray", protocol = "http" })
use_ipv6:depends({ type = "V2ray", protocol = "socks" })
use_ipv6:depends({ type = "V2ray", protocol = "shadowsocks" })
use_ipv6:depends({ type = "V2ray", protocol = "trojan" })
--]]
port = s:option(Value, "port", translate("Port"))
@ -257,20 +249,12 @@ port:depends({ type = "Xray", protocol = "http" })
port:depends({ type = "Xray", protocol = "socks" })
port:depends({ type = "Xray", protocol = "shadowsocks" })
port:depends({ type = "Xray", protocol = "trojan" })
port:depends({ type = "V2ray", protocol = "vmess" })
port:depends({ type = "V2ray", protocol = "vless" })
port:depends({ type = "V2ray", protocol = "http" })
port:depends({ type = "V2ray", protocol = "socks" })
port:depends({ type = "V2ray", protocol = "shadowsocks" })
port:depends({ type = "V2ray", protocol = "trojan" })
username = s:option(Value, "username", translate("Username"))
username:depends("type", "Socks")
username:depends("type", "Naiveproxy")
username:depends({ type = "Xray", protocol = "http" })
username:depends({ type = "Xray", protocol = "socks" })
username:depends({ type = "V2ray", protocol = "http" })
username:depends({ type = "V2ray", protocol = "socks" })
password = s:option(Value, "password", translate("Password"))
password.password = true
@ -286,10 +270,6 @@ password:depends({ type = "Xray", protocol = "http" })
password:depends({ type = "Xray", protocol = "socks" })
password:depends({ type = "Xray", protocol = "shadowsocks" })
password:depends({ type = "Xray", protocol = "trojan" })
password:depends({ type = "V2ray", protocol = "http" })
password:depends({ type = "V2ray", protocol = "socks" })
password:depends({ type = "V2ray", protocol = "shadowsocks" })
password:depends({ type = "V2ray", protocol = "trojan" })
ss_encrypt_method = s:option(ListValue, "ss_encrypt_method", translate("Encrypt Method"))
for a, t in ipairs(ss_encrypt_method_list) do ss_encrypt_method:value(t) end
@ -314,12 +294,10 @@ end
security = s:option(ListValue, "security", translate("Encrypt Method"))
for a, t in ipairs(security_list) do security:value(t) end
security:depends({ type = "Xray", protocol = "vmess" })
security:depends({ type = "V2ray", protocol = "vmess" })
encryption = s:option(Value, "encryption", translate("Encrypt Method"))
encryption.default = "none"
encryption:depends({ type = "Xray", protocol = "vless" })
encryption:depends({ type = "V2ray", protocol = "vless" })
v_ss_encrypt_method = s:option(ListValue, "v_ss_encrypt_method", translate("Encrypt Method"))
for a, t in ipairs(v_ss_encrypt_method_list) do v_ss_encrypt_method:value(t) end
@ -411,21 +389,10 @@ uuid = s:option(Value, "uuid", translate("ID"))
uuid.password = true
uuid:depends({ type = "Xray", protocol = "vmess" })
uuid:depends({ type = "Xray", protocol = "vless" })
uuid:depends({ type = "V2ray", protocol = "vmess" })
uuid:depends({ type = "V2ray", protocol = "vless" })
alter_id = s:option(Value, "alter_id", translate("Alter ID"))
alter_id:depends("protocol", "vmess")
level = s:option(Value, "level", translate("User Level"))
level.default = 1
level:depends({ type = "Xray", protocol = "vmess" })
level:depends({ type = "Xray", protocol = "vless" })
level:depends({ type = "Xray", protocol = "trojan" })
level:depends({ type = "V2ray", protocol = "vmess" })
level:depends({ type = "V2ray", protocol = "vless" })
level:depends({ type = "V2ray", protocol = "trojan" })
tls = s:option(Flag, "tls", translate("TLS"))
tls.default = 0
tls.validate = function(self, value, t)
@ -442,11 +409,6 @@ tls:depends({ type = "Xray", protocol = "vless" })
tls:depends({ type = "Xray", protocol = "socks" })
tls:depends({ type = "Xray", protocol = "trojan" })
tls:depends({ type = "Xray", protocol = "shadowsocks" })
tls:depends({ type = "V2ray", protocol = "vmess" })
tls:depends({ type = "V2ray", protocol = "vless" })
tls:depends({ type = "V2ray", protocol = "socks" })
tls:depends({ type = "V2ray", protocol = "shadowsocks" })
tls:depends({ type = "Xray", protocol = "trojan" })
tls:depends("type", "Trojan")
tls:depends("type", "Trojan-Plus")
tls:depends("type", "Trojan-Go")
@ -535,11 +497,6 @@ transport:depends({ type = "Xray", protocol = "vless" })
transport:depends({ type = "Xray", protocol = "socks" })
transport:depends({ type = "Xray", protocol = "shadowsocks" })
transport:depends({ type = "Xray", protocol = "trojan" })
transport:depends({ type = "V2ray", protocol = "vmess" })
transport:depends({ type = "V2ray", protocol = "vless" })
transport:depends({ type = "V2ray", protocol = "socks" })
transport:depends({ type = "V2ray", protocol = "shadowsocks" })
transport:depends({ type = "V2ray", protocol = "trojan" })
--[[
ss_transport = s:option(ListValue, "ss_transport", translate("Transport"))
@ -547,7 +504,6 @@ ss_transport:value("ws", "WebSocket")
ss_transport:value("h2", "HTTP/2")
ss_transport:value("h2+ws", "HTTP/2 & WebSocket")
ss_transport:depends({ type = "Xray", protocol = "shadowsocks" })
ss_transport:depends({ type = "V2ray", protocol = "shadowsocks" })
]]--
-- [[ TCP部分 ]]--
@ -667,11 +623,6 @@ mux:depends({ type = "Xray", protocol = "vless", xtls = false })
mux:depends({ type = "Xray", protocol = "http" })
mux:depends({ type = "Xray", protocol = "socks" })
mux:depends({ type = "Xray", protocol = "shadowsocks" })
mux:depends({ type = "V2ray", protocol = "vmess" })
mux:depends({ type = "V2ray", protocol = "vless" })
mux:depends({ type = "V2ray", protocol = "http" })
mux:depends({ type = "V2ray", protocol = "socks" })
mux:depends({ type = "V2ray", protocol = "shadowsocks" })
mux:depends("type", "Trojan-Go")
mux_concurrency = s:option(Value, "mux_concurrency", translate("Mux Concurrency"))
@ -683,7 +634,6 @@ mux_concurrency:depends("mux", "1")
tcp_socks = s:option(Flag, "tcp_socks", translate("TCP Open Socks"), translate("When using this TCP node, whether to open the socks proxy at the same time"))
tcp_socks.default = 0
tcp_socks:depends("type", "Xray")
tcp_socks:depends("type", "V2ray")
tcp_socks_port = s:option(Value, "tcp_socks_port", "Socks " .. translate("Port"), translate("Do not conflict with other ports"))
tcp_socks_port.datatype = "port"

View File

@ -63,7 +63,7 @@ if nodes_display:find("compact_display_nodes") then
local remarks = m:get(n, "remarks") or ""
local type = m:get(n, "type") or ""
str = str .. string.format("<input type='hidden' id='cbid.%s.%s.type' value='%s'/>", appname, n, type)
if type == "Xray" or type == "V2ray" then
if type == "Xray" then
local protocol = m:get(n, "protocol")
if protocol == "_balancing" then
type = type .. " 负载均衡"
@ -106,7 +106,7 @@ else
local v = Value.cfgvalue(t, n)
if v then
result = translate(v)
if v == "Xray" or v == "V2ray" then
if v == "Xray" then
local protocol = m:get(n, "protocol")
if protocol == "_balancing" then
result = result .. " 负载均衡"

View File

@ -49,7 +49,7 @@ for e = 0, 23 do o:value(e, e .. translate("oclock")) end
o.default = 0
o:depends("auto_update", 1)
s = m:section(TypedSection, "shunt_rules", "Xray/V2ray" .. translate("Shunt") .. translate("Rule"))
s = m:section(TypedSection, "shunt_rules", "Xray" .. translate("Shunt") .. translate("Rule"))
s.template = "cbi/tblsection"
s.anonymous = false
s.addremove = true

View File

@ -1,7 +1,7 @@
local d = require "luci.dispatcher"
local appname = "passwall"
m = Map(appname, "Xray/V2ray" .. translate("Shunt") .. translate("Rule"))
m = Map(appname, "Xray" .. translate("Shunt") .. translate("Rule"))
m.redirect = d.build_url("admin", "services", appname)
s = m:section(NamedSection, arg[1], "shunt_rules", "")

View File

@ -112,9 +112,6 @@ local function start()
elseif type == "Xray" then
config = require("luci.model.cbi.passwall.server.api.xray").gen_config(user)
bin = ln_start(_api.get_xray_path(), "xray", "-config=" .. config_file, log_path)
elseif type == "V2ray" then
config = require("luci.model.cbi.passwall.server.api.v2ray").gen_config(user)
bin = ln_start(_api.get_v2ray_path(), "v2ray", "-config=" .. config_file, log_path)
elseif type == "Trojan" then
config = require("luci.model.cbi.passwall.server.api.trojan").gen_config(user)
bin = ln_start("/usr/sbin/trojan", "trojan", "-c " .. config_file, log_path)

View File

@ -1,177 +0,0 @@
module("luci.model.cbi.passwall.server.api.v2ray", package.seeall)
local ucic = require"luci.model.uci".cursor()
function gen_config(user)
local settings = nil
local routing = nil
local outbounds = {
{protocol = "freedom", tag = "direct"}, {protocol = "blackhole", tag = "blocked"}
}
if user.protocol == "vmess" or user.protocol == "vless" then
if user.uuid then
local clients = {}
for i = 1, #user.uuid do
clients[i] = {
id = user.uuid[i],
flow = user.flow or nil,
level = tonumber(user.level),
alterId = tonumber(user.alter_id)
}
end
settings = {
clients = clients,
decryption = user.decryption or "none"
}
end
elseif user.protocol == "socks" then
settings = {
auth = (user.auth and user.auth == "1") and "password" or "noauth",
accounts = (user.auth and user.auth == "1") and {
{
user = user.username,
pass = user.password
}
}
}
elseif user.protocol == "http" then
settings = {
allowTransparent = false,
accounts = (user.auth and user.auth == "1") and {
{
user = user.username,
pass = user.password
}
}
}
user.transport = "tcp"
user.tcp_guise = "none"
elseif user.protocol == "shadowsocks" then
settings = {
method = user.method,
password = user.password,
level = tonumber(user.level) or 1,
network = user.ss_network or "TCP,UDP"
}
elseif user.protocol == "trojan" then
if user.uuid then
local clients = {}
for i = 1, #user.uuid do
clients[i] = {
password = user.uuid[i],
level = tonumber(user.level)
}
end
settings = {
clients = clients
}
end
elseif user.protocol == "mtproto" then
settings = {
users = {
{
level = tonumber(user.level) or 1,
secret = (user.password == nil) and "" or user.password
}
}
}
end
routing = {
domainStrategy = "IPOnDemand",
rules = {
{
type = "field",
ip = {"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"},
outboundTag = (user.accept_lan == nil or user.accept_lan == "0") and "blocked" or "direct"
}
}
}
if user.transit_node and user.transit_node ~= "nil" then
local gen_v2ray = require("luci.model.cbi.passwall.api.gen_v2ray")
local client = gen_v2ray.gen_outbound(ucic:get_all("passwall", user.transit_node), "transit")
table.insert(outbounds, 1, client)
end
local config = {
log = {
-- error = "/var/etc/passwall_server/log/" .. user[".name"] .. ".log",
loglevel = (user.log and user.log == "1") and user.loglevel or "none"
},
-- 传入连接
inbounds = {
{
listen = (user.bind_local == "1") and "127.0.0.1" or nil,
port = tonumber(user.port),
protocol = user.protocol,
settings = settings,
streamSettings = {
network = user.transport,
security = "none",
tlsSettings = (user.tls and user.tls == "1") and {
disableSystemRoot = false,
certificates = {
{
certificateFile = user.tls_certificateFile,
keyFile = user.tls_keyFile
}
}
} or nil,
tcpSettings = (user.transport == "tcp") and {
header = {
type = user.tcp_guise,
request = (user.tcp_guise == "http") and {
path = user.tcp_guise_http_path or {"/"},
headers = {
Host = user.tcp_guise_http_host or {}
}
} or nil
}
} or nil,
kcpSettings = (user.transport == "mkcp") and {
mtu = tonumber(user.mkcp_mtu),
tti = tonumber(user.mkcp_tti),
uplinkCapacity = tonumber(user.mkcp_uplinkCapacity),
downlinkCapacity = tonumber(user.mkcp_downlinkCapacity),
congestion = (user.mkcp_congestion == "1") and true or false,
readBufferSize = tonumber(user.mkcp_readBufferSize),
writeBufferSize = tonumber(user.mkcp_writeBufferSize),
seed = (user.mkcp_seed and user.mkcp_seed ~= "") and user.mkcp_seed or nil,
header = {type = user.mkcp_guise}
} or nil,
wsSettings = (user.transport == "ws") and {
acceptProxyProtocol = false,
headers = (user.ws_host) and {Host = user.ws_host} or nil,
path = user.ws_path
} or nil,
httpSettings = (user.transport == "h2") and {
path = user.h2_path, host = user.h2_host
} or nil,
dsSettings = (user.transport == "ds") and {
path = user.ds_path
} or nil,
quicSettings = (user.transport == "quic") and {
security = user.quic_security,
key = user.quic_key,
header = {type = user.quic_guise}
} or nil
}
}
},
-- 传出连接
outbounds = outbounds,
routing = routing
}
if user.tls and user.tls == "1" then
config.inbounds[1].streamSettings.security = "tls"
end
if user.transport == "mkcp" or user.transport == "quic" then
config.inbounds[1].streamSettings.security = "none"
config.inbounds[1].streamSettings.tlsSettings = nil
end
return config
end

View File

@ -47,7 +47,7 @@ e = t:option(DummyValue, "type", translate("Type"))
e.cfgvalue = function(t, n)
local v = Value.cfgvalue(t, n)
if v then
if v == "Xray" or v == "V2ray" then
if v == "Xray" then
local protocol = m:get(n, "protocol")
return v .. " -> " .. protocol
end

View File

@ -80,9 +80,6 @@ end
if api.is_finded("xray") then
type:value("Xray", translate("Xray"))
end
if api.is_finded("v2ray") then
type:value("V2ray", translate("V2ray"))
end
if api.is_finded("brook") then
type:value("Brook", translate("Brook"))
end
@ -107,7 +104,6 @@ protocol:value("shadowsocks", "Shadowsocks")
protocol:value("trojan", "Trojan")
protocol:value("mtproto", "MTProto")
protocol:depends("type", "Xray")
protocol:depends("type", "V2ray")
-- Brook协议
brook_protocol = s:option(ListValue, "brook_protocol", translate("Protocol"))
@ -142,8 +138,6 @@ end
auth:depends("type", "Socks")
auth:depends({ type = "Xray", protocol = "socks" })
auth:depends({ type = "Xray", protocol = "http" })
auth:depends({ type = "V2ray", protocol = "socks" })
auth:depends({ type = "V2ray", protocol = "http" })
username = s:option(Value, "username", translate("Username"))
username:depends("auth", "1")
@ -155,11 +149,9 @@ password:depends("type", "SS")
password:depends("type", "SSR")
password:depends("type", "Brook")
password:depends({ type = "Xray", protocol = "shadowsocks" })
password:depends({ type = "V2ray", protocol = "shadowsocks" })
mtproto_password = s:option(Value, "mtproto_password", translate("Password"), translate("The MTProto protocol must be 32 characters and can only contain characters from 0 to 9 and a to f."))
mtproto_password:depends({ type = "Xray", protocol = "mtproto" })
mtproto_password:depends({ type = "V2ray", protocol = "mtproto" })
mtproto_password.default = arg[1]
function mtproto_password.cfgvalue(self, section)
return m:get(section, "password")
@ -171,7 +163,6 @@ end
decryption = s:option(Value, "decryption", translate("Encrypt Method"))
decryption.default = "none"
decryption:depends({ type = "Xray", protocol = "vless" })
decryption:depends({ type = "V2ray", protocol = "vless" })
ss_encrypt_method = s:option(ListValue, "ss_encrypt_method", translate("Encrypt Method"))
for a, t in ipairs(ss_encrypt_method_list) do ss_encrypt_method:value(t) end
@ -196,7 +187,6 @@ end
v_ss_encrypt_method = s:option(ListValue, "v_ss_encrypt_method", translate("Encrypt Method"))
for a, t in ipairs(v_ss_encrypt_method_list) do v_ss_encrypt_method:value(t) end
v_ss_encrypt_method:depends({ type = "Xray", protocol = "shadowsocks" })
v_ss_encrypt_method:depends({ type = "V2ray", protocol = "shadowsocks" })
function v_ss_encrypt_method.cfgvalue(self, section)
return m:get(section, "method")
end
@ -210,7 +200,6 @@ ss_network:value("tcp", "TCP")
ss_network:value("udp", "UDP")
ss_network:value("tcp,udp", "TCP,UDP")
ss_network:depends({ type = "Xray", protocol = "shadowsocks" })
ss_network:depends({ type = "V2ray", protocol = "shadowsocks" })
ssr_protocol = s:option(ListValue, "ssr_protocol", translate("Protocol"))
for a, t in ipairs(ssr_protocol_list) do ssr_protocol:value(t) end
@ -250,16 +239,12 @@ end
uuid:depends({ type = "Xray", protocol = "vmess" })
uuid:depends({ type = "Xray", protocol = "vless" })
uuid:depends({ type = "Xray", protocol = "trojan" })
uuid:depends({ type = "V2ray", protocol = "vmess" })
uuid:depends({ type = "V2ray", protocol = "vless" })
uuid:depends({ type = "V2ray", protocol = "trojan" })
uuid:depends("type", "Trojan")
uuid:depends("type", "Trojan-Go")
uuid:depends("type", "Trojan-Plus")
alter_id = s:option(Value, "alter_id", translate("Alter ID"))
alter_id:depends({ type = "Xray", protocol = "vmess" })
alter_id:depends({ type = "V2ray", protocol = "vmess" })
level = s:option(Value, "level", translate("User Level"))
level:depends({ type = "Xray", protocol = "vmess" })
@ -267,11 +252,6 @@ level:depends({ type = "Xray", protocol = "vless" })
level:depends({ type = "Xray", protocol = "shadowsocks" })
level:depends({ type = "Xray", protocol = "trojan" })
level:depends({ type = "Xray", protocol = "mtproto" })
level:depends({ type = "V2ray", protocol = "vmess" })
level:depends({ type = "V2ray", protocol = "vless" })
level:depends({ type = "V2ray", protocol = "shadowsocks" })
level:depends({ type = "V2ray", protocol = "trojan" })
level:depends({ type = "V2ray", protocol = "mtproto" })
tls = s:option(Flag, "tls", translate("TLS"))
tls.default = 0
@ -296,10 +276,6 @@ tls:depends({ type = "Xray", protocol = "vless" })
tls:depends({ type = "Xray", protocol = "socks" })
tls:depends({ type = "Xray", protocol = "shadowsocks" })
tls:depends({ type = "Xray", protocol = "trojan" })
tls:depends({ type = "V2ray", protocol = "vmess" })
tls:depends({ type = "V2ray", protocol = "vless" })
tls:depends({ type = "V2ray", protocol = "socks" })
tls:depends({ type = "V2ray", protocol = "shadowsocks" })
tls:depends("type", "Trojan")
tls:depends("type", "Trojan-Plus")
tls:depends("type", "Trojan-Go")
@ -374,11 +350,6 @@ transport:depends({ type = "Xray", protocol = "vless" })
transport:depends({ type = "Xray", protocol = "socks" })
transport:depends({ type = "Xray", protocol = "shadowsocks" })
transport:depends({ type = "Xray", protocol = "trojan" })
transport:depends({ type = "V2ray", protocol = "vmess" })
transport:depends({ type = "V2ray", protocol = "vless" })
transport:depends({ type = "V2ray", protocol = "socks" })
transport:depends({ type = "V2ray", protocol = "shadowsocks" })
transport:depends({ type = "V2ray", protocol = "trojan" })
trojan_transport = s:option(ListValue, "trojan_transport", translate("Transport"))
trojan_transport:value("original", "Original")
@ -512,15 +483,11 @@ quic_guise:depends("transport", "quic")
acceptProxyProtocol = s:option(Flag, "acceptProxyProtocol", translate("acceptProxyProtocol"), translate("Whether to receive PROXY protocol, when this node want to be fallback or forwarded by proxy, it must be enable, otherwise it cannot be used."))
acceptProxyProtocol:depends({ type = "Xray", transport = "tcp" })
acceptProxyProtocol:depends({ type = "Xray", transport = "ws" })
acceptProxyProtocol:depends({ type = "V2ray", transport = "tcp" })
acceptProxyProtocol:depends({ type = "V2ray", transport = "ws" })
-- [[ Fallback部分 ]]--
fallback = s:option(Flag, "fallback", translate("Fallback"))
fallback:depends({ type = "Xray", protocol = "vless", transport = "tcp" })
fallback:depends({ type = "Xray", protocol = "trojan", transport = "tcp" })
fallback:depends({ type = "V2ray", protocol = "vless", transport = "tcp" })
fallback:depends({ type = "V2ray", protocol = "trojan", transport = "tcp" })
--[[
fallback_alpn = s:option(Value, "fallback_alpn", "Fallback alpn")
@ -580,17 +547,15 @@ remote_port:depends("remote_enable", 1)
bind_local = s:option(Flag, "bind_local", translate("Bind Local"), translate("When selected, it can only be accessed locally, It is recommended to turn on when using reverse proxies or be fallback."))
bind_local.default = "0"
bind_local:depends("type", "Xray")
bind_local:depends("type", "V2ray")
accept_lan = s:option(Flag, "accept_lan", translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
accept_lan.default = "0"
accept_lan.rmempty = false
accept_lan:depends("type", "Xray")
accept_lan:depends("type", "V2ray")
local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do
if e.node_type == "normal" and e.type == "Xray" or e.type == "V2ray" then
if e.node_type == "normal" and e.type == "Xray" then
nodes_table[#nodes_table + 1] = {
id = e[".name"],
remarks = e.remarks_name
@ -603,7 +568,6 @@ transit_node:value("nil", translate("Close"))
for k, v in pairs(nodes_table) do transit_node:value(v.id, v.remarks) end
transit_node.default = "nil"
transit_node:depends("type", "Xray")
transit_node:depends("type", "V2ray")
log = s:option(Flag, "log", translate("Enable") .. translate("Log"))
log.default = "1"
@ -616,7 +580,6 @@ loglevel:value("info")
loglevel:value("warning")
loglevel:value("error")
loglevel:depends({ type = "Xray", log = true })
loglevel:depends({ type = "V2ray", log = true })
trojan_loglevel = s:option(ListValue, "trojan_loglevel", translate("Log Level"))
trojan_loglevel.default = "2"

View File

@ -1,172 +0,0 @@
<%
local v2ray_version = require "luci.model.cbi.passwall.api.api".get_v2ray_version()
-%>
<script type="text/javascript">
//<![CDATA[
var v2rayInfo;
var tokenStr = '<%=token%>';
var manuallyUpdateText = '<%:Manually update%>';
var noUpdateText = '<%:It is the latest version%>';
var updateSuccessText = '<%:Update successful%>';
var clickToUpdateText = '<%:Click to update%>';
var inProgressText = '<%:Updating...%>';
var unexpectedErrorText = '<%:Unexpected error%>';
var updateInProgressNotice = '<%:Updating, are you sure to close?%>';
var downloadingText = '<%:Downloading...%>';
var decompressioningText = '<%:Unpacking...%>';
var movingText = '<%:Moving...%>';
window.onload = function() {
var v2rayCheckBtn = document.getElementById('_v2ray-check_btn');
var v2rayDetailElm = document.getElementById('_v2ray-check_btn-detail');
};
function addPageNotice_v2ray() {
window.onbeforeunload = function(e) {
e.returnValue = updateInProgressNotice;
return updateInProgressNotice;
};
}
function removePageNotice_v2ray() {
window.onbeforeunload = undefined;
}
function onUpdateSuccess_v2ray(btn) {
alert(updateSuccessText);
if(btn) {
btn.value = updateSuccessText;
btn.placeholder = updateSuccessText;
btn.disabled = true;
}
window.setTimeout(function() {
window.location.reload();
}, 1000);
}
function onRequestError_v2ray(btn, errorMessage) {
btn.disabled = false;
btn.value = manuallyUpdateText;
if(errorMessage) {
alert(errorMessage);
}
}
function onBtnClick_v2ray(btn) {
if(v2rayInfo === undefined) {
checkUpdate_v2ray(btn);
} else {
doUpdate_v2ray(btn);
}
}
function checkUpdate_v2ray(btn) {
btn.disabled = true;
btn.value = inProgressText;
addPageNotice_v2ray();
var ckeckDetailElm = document.getElementById(btn.id + '-detail');
XHR.get('<%=url([[admin]], [[services]], [[passwall]], [[v2ray_check]])%>', {
token: tokenStr,
arch: ''
}, function(x,json) {
removePageNotice_v2ray();
if(json.code) {
v2rayInfo = undefined;
onRequestError_v2ray(btn, json.error);
} else {
if(json.update) {
v2rayInfo = json;
btn.disabled = false;
btn.value = clickToUpdateText;
btn.placeholder = clickToUpdateText;
if(ckeckDetailElm) {
var urlNode = '';
if(json.version) {
urlNode = '<em style="color:red;">最新版本号:' + json.version + '</em>';
if(json.url && json.url.html) {
urlNode = '<a href="' + json.url.html + '" target="_blank">' + urlNode + '</a>';
}
}
ckeckDetailElm.innerHTML = urlNode;
}
} else {
btn.disabled = true;
btn.value = noUpdateText;
}
}
},300);
}
function doUpdate_v2ray(btn) {
btn.disabled = true;
btn.value = downloadingText;
addPageNotice_v2ray();
var v2rayUpdateUrl = '<%=url([[admin]], [[services]], [[passwall]], [[v2ray_update]])%>';
// Download file
XHR.get(v2rayUpdateUrl, {
token: tokenStr,
url: v2rayInfo ? v2rayInfo.url.download : ''
}, function(x,json) {
if(json.code) {
removePageNotice_v2ray();
onRequestError_v2ray(btn, json.error);
} else {
btn.value = decompressioningText;
// Extract file
XHR.get(v2rayUpdateUrl, {
token: tokenStr,
task: 'extract',
file: json.file,
subfix: v2rayInfo ? v2rayInfo.type : ''
}, function(x,json) {
if(json.code) {
removePageNotice_v2ray();
onRequestError_v2ray(btn, json.error);
} else {
btn.value = movingText;
// Move file to target dir
XHR.get(v2rayUpdateUrl, {
token: tokenStr,
task: 'move',
file: json.file
}, function(x,json) {
removePageNotice_v2ray();
if(json.code) {
onRequestError_v2ray(btn, json.error);
} else {
onUpdateSuccess_v2ray(btn);
}
},300)
}
},300)
}
},300)
}
//]]>
</script>
<div class="cbi-value">
<label class="cbi-value-title">V2ray
<%:Version%>
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<span><%=v2ray_version%> 】</span>
<input class="cbi-button cbi-input-apply" type="button" id="_v2ray-check_btn" onclick="onBtnClick_v2ray(this);" value="<%:Manually update%>" />
<span id="_v2ray-check_btn-detail"></span>
</div>
</div>
</div>

View File

@ -1,8 +1,6 @@
<%+cbi/valueheader%>
<%
local dsp = require "luci.dispatcher"
local api = require "luci.model.cbi.passwall.api.api"
-%>
<script type="text/javascript">//<![CDATA[
function padright(str, cnt, pad) {
@ -314,6 +312,8 @@ local api = require "luci.model.cbi.passwall.api.api"
if (ploc > 0) {
url0 = sstr.substr(0, ploc);
param = sstr.substr(ploc + 2);
} else {
var url0 = sstr;
}
console.log(param);
var ssm = url0.match(/^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)/);
@ -556,10 +556,7 @@ local api = require "luci.model.cbi.passwall.api.api"
} else if (ssu[0] === "vmess") {
var sstr = b64DecodeUnicode(ssu[1]);
var ploc = sstr.indexOf("/?");
opt.set('type', "V2ray");
<% if api.is_finded("xray") then -%>
opt.set('type', "Xray");
<% end -%>
opt.set('type', "Xray");
opt.get('type').dispatchEvent(event);
var url0, param = "";
if (ploc > 0) {

View File

@ -160,12 +160,18 @@ msgstr "自定义DNS"
msgid "IP:Port mode ecceptable for specify other filtered name services."
msgstr "定义接受 IP:Port 形式的输入,以指定其它域名服务的过滤服务。"
msgid "Resolver For Local/WhiteList Domains"
msgstr "解析本地和白名单域名"
msgid "Local DNS"
msgstr "本地DNS"
msgid "Remote DNS"
msgstr "远程DNS"
msgid "IP:Port mode acceptable, multi value split with english comma."
msgstr "接受 IP:Port 形式的输入,多个以英文逗号分隔。"
msgid "If you use dns2socks, only the first one is valid."
msgstr "如果使用dns2socks只有第一个生效。"
msgid "When the selection is not the default, this DNS is forced to be set to dnsmasq upstream DNS."
msgstr "当选择的不是默认则将此DNS强制设置为dnsmasq上游DNS。"
@ -214,9 +220,6 @@ msgstr "请确保此Socks服务可用。"
msgid "ChinaDNS-NG Fair Mode"
msgstr "ChinaDNS-NG 公平模式"
msgid "Filtered DNS(For Proxied Domains)"
msgstr "域名过滤服务(用于被代理的域名)"
msgid "Format must be:"
msgstr "格式必须为:"
@ -229,9 +232,6 @@ msgstr "DoH Bootstrap DNS"
msgid "The Bootstrap DNS server is used to resolve the IP address of the DoH resolver you specify as the upstream."
msgstr "Bootstrap DNS 服务器用于解析您指定为上游的 DoH 解析器的 IP 地址。"
msgid "IP:Port mode acceptable, the 1st for 'dns2socks' if split with english comma."
msgstr "接受 IP:Port 形式的输入,多个以英文逗号分隔 'dns2socks' 模式下仅首个有效。"
msgid "Cache Resolved"
msgstr "缓存解析结果"
@ -412,6 +412,9 @@ msgstr "前置代理"
msgid "Use the default node for the transit."
msgstr "使用默认节点代理转发。"
msgid "Use the under node for the transit."
msgstr "使用下面的节点代理转发。"
msgid "No shunt rules? Click me to go to add."
msgstr "没有分流规则?点我前往去添加。"

View File

@ -6,14 +6,12 @@ config global
option udp_node 'nil'
option dns_mode 'pdnsd'
option up_china_dns 'default'
option dns_forward '8.8.4.4'
option use_chnlist '0'
option use_tcp_node_resolve_dns '1'
option dns_forward '8.8.8.8'
option tcp_proxy_mode 'chnroute'
option udp_proxy_mode 'chnroute'
option localhost_tcp_proxy_mode 'gfwlist'
option localhost_udp_proxy_mode 'gfwlist'
option socks_server '0.0.0.0:1080'
option localhost_tcp_proxy_mode 'chnroute'
option localhost_udp_proxy_mode 'chnroute'
option socks_server '127.0.0.1:9050'
option close_log_tcp '1'
option close_log_udp '1'
option loglevel 'warning'
@ -52,7 +50,6 @@ config global_rules
config global_app
option xray_file '/usr/bin/xray'
option v2ray_file '/usr/bin/v2ray'
option trojan_go_file '/usr/bin/trojan-go'
option kcptun_client_file '/usr/bin/kcptun-client'
option brook_file '/usr/bin/brook'

View File

@ -298,7 +298,6 @@ load_config() {
DNS_MODE=$(config_t_get global dns_mode pdnsd)
DNS_FORWARD=$(config_t_get global dns_forward 8.8.4.4:53 | sed 's/:/#/g')
DNS_CACHE=$(config_t_get global dns_cache 1)
USE_CHNLIST=$(config_t_get global use_chnlist 0)
process=1
if [ "$(config_t_get global_forwarding process 0)" = "0" ]; then
process=$(cat /proc/cpuinfo | grep 'processor' | wc -l)
@ -318,13 +317,13 @@ load_config() {
}
run_socks() {
local node=$1
local bind=$2
local socks_port=$3
local config_file=$4
local http_port=$5
local http_config_file=$6
local id=$7
local flag=$1
local node=$2
local bind=$3
local socks_port=$4
local config_file=$5
local http_port=$6
local http_config_file=$7
local relay_port=$8
local log_file="/dev/null"
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
@ -345,7 +344,7 @@ run_socks() {
msg="某种原因,此 Socks 服务的相关配置已失联,启动中止!"
fi
if [ "$type" == "xray" -o "$type" == "v2ray" ] && ([ -n "$(config_n_get $node balancing_node)" ] || [ "$(config_n_get $node default_node)" != "nil" ]); then
if [ "$type" == "xray" ] && ([ -n "$(config_n_get $node balancing_node)" ] || [ "$(config_n_get $node default_node)" != "nil" ]); then
unset msg
fi
@ -356,20 +355,15 @@ run_socks() {
[ "$bind" != "127.0.0.1" ] && echolog " - 启动 ${bind}:${socks_port} - 节点:$remarks${tmp}"
case "$type" in
socks)
_username=$(config_n_get $node username)
_password=$(config_n_get $node password)
[ -n "$_username" ] && [ -n "$_password" ] && local _auth="--uname $_username --passwd $_password"
ln_start_bin "$(first_type ssocks)" ssocks_SOCKS_$id $log_file --listen $socks_port --socks $server_host:$port $_auth
;;
socks|\
xray)
lua $API_GEN_XRAY -node $node -socks_proxy_port $socks_port > $config_file
[ "$http_port" != "0" ] && {
local extra_param="-http_proxy_port $http_port"
config_file=$(echo $config_file | sed "s/SOCKS/HTTP_SOCKS/g")
}
lua $API_GEN_XRAY -node $node -socks_proxy_port $socks_port $extra_param > $config_file
ln_start_bin "$(first_type $(config_t_get global_app xray_file) xray)" xray $log_file -config="$config_file"
;;
v2ray)
lua $API_GEN_XRAY -node $node -socks_proxy_port $socks_port > $config_file
ln_start_bin "$(first_type $(config_t_get global_app v2ray_file) v2ray)" v2ray $log_file -config="$config_file"
;;
trojan-go)
lua $API_GEN_TROJAN -node $node -run_type client -local_addr $bind -local_port $socks_port -server_host $server_host -server_port $port > $config_file
ln_start_bin "$(first_type $(config_t_get global_app trojan_go_file) trojan-go)" trojan-go $log_file -config "$config_file"
@ -388,21 +382,20 @@ run_socks() {
[ "$protocol" == "wsclient" ] && {
[ "$brook_tls" == "1" ] && server_host="wss://${server_host}" || server_host="ws://${server_host}"
}
ln_start_bin "$(first_type $(config_t_get global_app brook_file) brook)" "brook_SOCKS_$id" $log_file "$protocol" --socks5 "$bind:$socks_port" -s "$server_host:$port" -p "$(config_n_get $node password)"
ln_start_bin "$(first_type $(config_t_get global_app brook_file) brook)" "brook_SOCKS_${flag}" $log_file "$protocol" --socks5 "$bind:$socks_port" -s "$server_host:$port" -p "$(config_n_get $node password)"
;;
ss|ssr)
lua $API_GEN_SS -node $node -local_addr "0.0.0.0" -local_port $socks_port -server_host $server_host -server_port $port > $config_file
ln_start_bin "$(first_type ${type}-local)" "${type}-local" $log_file -c "$config_file" -b "$bind" -u
ln_start_bin "$(first_type ${type}-local)" "${type}-local" $log_file -c "$config_file" -b "$bind" -u -v
;;
esac
# socks to http
[ "$http_port" != "0" ] && [ "$http_config_file" != "nil" ] && {
[ "$type" != "xray" ] && [ "$type" != "socks" ] && [ "$http_port" != "0" ] && [ "$http_config_file" != "nil" ] && {
lua $API_GEN_XRAY_PROTO -local_proto http -local_address "0.0.0.0" -local_port $http_port -server_proto socks -server_address "127.0.0.1" -server_port $socks_port -server_username $_username -server_password $_password > $http_config_file
echo lua $API_GEN_XRAY_PROTO -local_proto http -local_address "0.0.0.0" -local_port $http_port -server_proto socks -server_address "127.0.0.1" -server_port $socks_port -server_username $_username -server_password $_password
ln_start_bin "$(first_type $(config_t_get global_app xray_file) xray)" xray $log_file -config="$http_config_file"
}
unset _username _password _auth
}
run_redir() {
@ -443,18 +436,13 @@ run_redir() {
local server_username=$(config_n_get $node username)
local server_password=$(config_n_get $node password)
eval port=\$UDP_REDIR_PORT
ln_start_bin "$(first_type ipt2socks)" "ipt2socks_udp" $log_file -U -l "$port" -b 0.0.0.0 -s "$node_address" -p "$node_port" -R
ln_start_bin "$(first_type ipt2socks)" "ipt2socks_udp" $log_file -U -l "$port" -b 0.0.0.0 -s "$node_address" -p "$node_port" -R -v
;;
xray)
local loglevel=$(config_t_get global loglevel "warning")
lua $API_GEN_XRAY -node $node -proto udp -redir_port $local_port -loglevel $loglevel > $config_file
ln_start_bin "$(first_type $(config_t_get global_app xray_file) xray)" xray $log_file -config="$config_file"
;;
v2ray)
local loglevel=$(config_t_get global loglevel "warning")
lua $API_GEN_XRAY -node $node -proto udp -redir_port $local_port -loglevel $loglevel > $config_file
ln_start_bin "$(first_type $(config_t_get global_app v2ray_file) v2ray)" v2ray $log_file -config="$config_file"
;;
trojan-go)
local loglevel=$(config_t_get global trojan_loglevel "2")
lua $API_GEN_TROJAN -node $node -run_type nat -local_addr "0.0.0.0" -local_port $local_port -loglevel $loglevel > $config_file
@ -478,7 +466,7 @@ run_redir() {
;;
ss|ssr)
lua $API_GEN_SS -node $node -local_addr "0.0.0.0" -local_port $local_port > $config_file
ln_start_bin "$(first_type ${type}-redir)" "${type}-redir" $log_file -c "$config_file" -U
ln_start_bin "$(first_type ${type}-redir)" "${type}-redir" $log_file -c "$config_file" -U -v
;;
esac
;;
@ -512,18 +500,20 @@ run_redir() {
;;
xray)
local loglevel=$(config_t_get global loglevel "warning")
local extra_param="tcp"
[ "$UDP_NODE" == "tcp" ] && extra_param="tcp,udp"
lua $API_GEN_XRAY -node $node -proto $extra_param -redir_port $local_port -loglevel $loglevel > $config_file
local proto="-proto tcp"
[ "$UDP_NODE" == "tcp" ] && proto="-proto tcp,udp"
local extra_param="${proto}"
[ "$(config_t_get global tcp_node_socks 0)" = "1" ] && {
local socks_param="-socks_proxy_port $(config_t_get global tcp_node_socks_port 1080)"
extra_param="${extra_param} ${socks_param}"
}
[ "$(config_t_get global tcp_node_http 0)" = "1" ] && {
local http_param="-http_proxy_port $(config_t_get global tcp_node_http_port 1180)"
extra_param="${extra_param} ${http_param}"
}
lua $API_GEN_XRAY -node $node -redir_port $local_port -loglevel $loglevel $extra_param > $config_file
ln_start_bin "$(first_type $(config_t_get global_app xray_file) xray)" xray $log_file -config="$config_file"
;;
v2ray)
local loglevel=$(config_t_get global loglevel "warning")
local extra_param="tcp"
[ "$UDP_NODE" == "tcp" ] && extra_param="tcp,udp"
lua $API_GEN_XRAY -node $node -proto $extra_param -redir_port $local_port -loglevel $loglevel > $config_file
ln_start_bin "$(first_type $(config_t_get global_app v2ray_file) v2ray)" v2ray $log_file -config="$config_file"
;;
trojan-go)
local loglevel=$(config_t_get global trojan_loglevel "2")
lua $API_GEN_TROJAN -node $node -run_type nat -local_addr "0.0.0.0" -local_port $local_port -loglevel $loglevel > $config_file
@ -571,14 +561,14 @@ run_redir() {
[ "$UDP_NODE" == "tcp" ] && extra_param="-u"
fi
for k in $(seq 1 $process); do
ln_start_bin "$(first_type ${type}-redir)" "${type}-redir" $log_file -c "$config_file" $extra_param
ln_start_bin "$(first_type ${type}-redir)" "${type}-redir" $log_file -c "$config_file" -v $extra_param
done
;;
esac
if [ -n "$_socks_flag" ]; then
local extra_param="-T"
[ "$UDP_NODE" == "tcp" ] && extra_param=""
ln_start_bin "$(first_type ipt2socks)" "ipt2socks_tcp" $log_file -l "$local_port" -b 0.0.0.0 -s "$_socks_address" -p "$_socks_port" -R $extra_param
ln_start_bin "$(first_type ipt2socks)" "ipt2socks_tcp" $log_file -l "$local_port" -b 0.0.0.0 -s "$_socks_address" -p "$_socks_port" -R -v $extra_param
fi
unset _socks_flag _socks_address _socks_port _socks_username _socks_password
;;
@ -620,22 +610,32 @@ start_redir() {
}
start_socks() {
[ "$(config_n_get $TCP_NODE type nil)" != "xray" ] && {
[ "$(config_t_get global tcp_node_socks 0)" = "1" ] && {
local port=$(config_t_get global tcp_node_socks_port 1080)
local config_file=$TMP_PATH/SOCKS_TCP.json
local log_file=$TMP_PATH/SOCKS_TCP.log
}
local http_port=0
local http_config_file=$TMP_PATH/HTTP2SOCKS_TCP.json
[ "$(config_t_get global tcp_node_http 0)" = "1" ] && {
http_port=$(config_t_get global tcp_node_http_port 1180)
}
run_socks TCP $TCP_NODE "0.0.0.0" $port $config_file $http_port $http_config_file
}
local ids=$(uci show $CONFIG | grep "=socks" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
echolog "分析 Socks 服务的节点配置..."
for id in $ids; do
local enabled=$(config_n_get $id enabled 0)
[ "$enabled" == "0" ] && continue
local node=$(config_n_get $id node nil)
if [ "$(echo $node | grep ^tcp)" ]; then
eval node=\$TCP_NODE
fi
[ "$node" == "nil" ] && continue
local port=$(config_n_get $id port)
local config_file=$TMP_PATH/SOCKS_${id}.json
local log_file=$TMP_PATH/SOCKS_${id}.log
local http_port=$(config_n_get $id http_port 0)
local http_config_file=$TMP_PATH/SOCKS2HTTP_${id}.json
run_socks $node "0.0.0.0" $port $config_file $http_port $http_config_file $id
local http_config_file=$TMP_PATH/HTTP2SOCKS_${id}.json
run_socks $id $node "0.0.0.0" $port $config_file $http_port $http_config_file
done
}
@ -718,16 +718,20 @@ stop_crontab() {
}
start_dns() {
if [ "${LOCAL_DNS}" = "https-dns-proxy" ]; then
_doh=$(config_t_get global up_china_dns_doh "https://dns.alidns.com/dns-query,223.5.5.5,223.6.6.6,2400:3200::1,2400:3200:baba::1")
if [ "${LOCAL_DNS}" = "xray_doh" ]; then
_doh=$(config_t_get global up_china_dns_doh "https://dns.alidns.com/dns-query,223.5.5.5")
_doh_url=$(echo $_doh | awk -F ',' '{print $1}')
_doh_host_port=$(echo $_doh_url | sed "s/https:\/\///g" | awk -F '/' '{print $1}')
_doh_host=$(echo $_doh_host_port | awk -F ':' '{print $1}')
_doh_port=$(echo $_doh_host_port | awk -F ':' '{print $2}')
_doh_bootstrap=$(echo $_doh | cut -d ',' -sf 2-)
ln_start_bin "$(first_type https-dns-proxy)" https-dns-proxy "/dev/null" -a 127.0.0.1 -p "${LOCAL_DOH_PORT}" -b "${_doh_bootstrap}" -r "${_doh_url}" -4
lua $API_GEN_XRAY -dns_listen_port "${LOCAL_DOH_PORT}" -dns_server "${_doh_bootstrap}" -doh_url "${_doh_url}" -doh_host "${_doh_host}" > $TMP_PATH/DNS1.json
ln_start_bin "$(first_type $(config_t_get global_app xray_file) xray)" xray $TMP_PATH/DNS1.log -config="$TMP_PATH/DNS1.json"
LOCAL_DNS="127.0.0.1#${LOCAL_DOH_PORT}"
unset _doh _doh_url _doh_bootstrap
fi
local pdnsd_forward other_port up_trust_pdnsd_dns msg
local pdnsd_forward other_port msg
local global chnlist returnhome china_ng_chn china_ng_gfw chnlist_param gfwlist_param extra_mode
dns_listen_port=${DNS_PORT}
pdnsd_forward=${DNS_FORWARD}
@ -741,6 +745,12 @@ start_dns() {
sed -n 's/^ipset=\/\.\?\([^/]*\).*$/\1/p' "${RULES_PATH}/gfwlist.conf" | sort -u > "${TMP_PATH}/gfwlist.txt"
echolog "过滤服务配置:准备接管域名解析[$?]..."
USE_CHNLIST=1
if [ ! -f "${RULES_PATH}/chnlist" ]; then
USE_CHNLIST=0
else
cp -a "${RULES_PATH}/chnlist" "${TMP_PATH}/chnlist"
fi
[ "$CHINADNS_NG" = "1" ] && {
echolog " | - (chinadns-ng) 只支持2~4级的域名过滤..."
[ -z "${global}${chnlist}" ] && echolog " | - (chinadns-ng) 此模式下列表外的域名查询会同时发送给本地DNS(可切换到Pdnsd + TCP节点模式解决)..."
@ -752,8 +762,8 @@ start_dns() {
elif [ "$DNS_MODE" = "dns2socks" ]; then
#[ -n "${global}${chnlist}" ] && TUN_DNS=${china_ng_gfw}
msg="dns2socks"
elif [ "$DNS_MODE" = "https-dns-proxy" ]; then
msg="https-dns-proxy(DoH)"
elif [ "$DNS_MODE" = "xray_doh" ]; then
msg="Xray DNS(DoH)"
elif [ "$DNS_MODE" = "udp" ]; then
use_udp_node_resolve_dns=1
if [ -z "${returnhome}" ]; then
@ -767,27 +777,27 @@ start_dns() {
china_ng_gfw="$(echo ${custom_dns} | sed 's/:/#/g')"
msg="自定义DNS"
fi
chnlist_param=
[ "$USE_CHNLIST" = "1" ] && {
cp -a "${RULES_PATH}/chnlist" "${TMP_PATH}/chnlist"
if [ -z "${returnhome}" ]; then
cat "${RULES_PATH}/direct_host" >> "${TMP_PATH}/chnlist"
echolog " | - [$?](chinadns-ng) 域名白名单合并到中国域名表"
cat "${RULES_PATH}/proxy_host" >> "${TMP_PATH}/gfwlist.txt"
[ -f "${RULES_PATH}/proxy_host2" ] && cat "${RULES_PATH}/proxy_host2" >> "${TMP_PATH}/gfwlist.txt"
[ -f "${RULES_PATH}/proxy_host3" ] && cat "${RULES_PATH}/proxy_host3" >> "${TMP_PATH}/gfwlist.txt"
echolog " | - [$?](chinadns-ng) 代理域名表合并到防火墙域名表"
gfwlist_param="${TMP_PATH}/gfwlist.txt"
else
echolog " | - (chinadns-ng) 白名单不与中国域名表合并"
cat "${RULES_PATH}/proxy_host" >> "${TMP_PATH}/chnlist"
[ -f "${RULES_PATH}/proxy_host2" ] && cat "${RULES_PATH}/proxy_host2" >> "${TMP_PATH}/chnlist"
[ -f "${RULES_PATH}/proxy_host3" ] && cat "${RULES_PATH}/proxy_host3" >> "${TMP_PATH}/chnlist"
chnlist_param="${TMP_PATH}/chnlist"
if [ -n "${returnhome}" ]; then
echolog " | - (chinadns-ng) 白名单不与中国域名表合并"
[ -f "${RULES_PATH}/proxy_host" ] && {
cat "${RULES_PATH}/proxy_host" >> "${chnlist_param}"
echolog " | - [$?](chinadns-ng) 忽略防火墙域名表,代理域名表合并到中国域名表"
fi
chnlist_param="${TMP_PATH}/chnlist"
chnlist_param=${chnlist_param:+-m "${chnlist_param}" -M}
}
}
else
[ -f "${RULES_PATH}/direct_host" ] && {
cat "${RULES_PATH}/direct_host" >> "${chnlist_param}"
echolog " | - [$?](chinadns-ng) 域名白名单合并到中国域名表"
}
[ -f "${RULES_PATH}/proxy_host" ] && {
gfwlist_param="${TMP_PATH}/gfwlist.txt"
cat "${RULES_PATH}/proxy_host" >> "${gfwlist_param}"
echolog " | - [$?](chinadns-ng) 代理域名表合并到防火墙域名表"
}
fi
chnlist_param=${chnlist_param:+-m "${chnlist_param}" -M}
[ "$(config_t_get global fair_mode 1)" = "1" ] && extra_mode="-f"
ln_start_bin "$(first_type chinadns-ng)" chinadns-ng "/dev/null" -l "${dns_listen_port}" ${china_ng_chn:+-c "${china_ng_chn}"} ${chnlist_param} ${china_ng_gfw:+-t "${china_ng_gfw}"} ${gfwlist_param:+-g "${gfwlist_param}"} $extra_mode
echolog " + 过滤服务ChinaDNS-NG(:${dns_listen_port}${extra_mode}) + ${msg}:中国域名列表:${china_ng_chn:-D114.114.114.114},防火墙域名列表:${china_ng_gfw:-D8.8.8.8}"
@ -801,9 +811,14 @@ start_dns() {
TUN_DNS=""
;;
dns2socks)
local dns2socks_socks_server=$(echo $(config_t_get global socks_server 127.0.0.1:9050) | sed "s/#/:/g")
local dns2socks_forward=$(get_first_dns DNS_FORWARD 53 | sed 's/#/:/g')
[ "$DNS_CACHE" == "0" ] && local dns2sock_cache="/d"
ln_start_bin "$(first_type dns2socks)" dns2socks "/dev/null" "$dns2socks_socks_server" "$dns2socks_forward" "127.0.0.1:$dns_listen_port" $dns2sock_cache
echolog " - dns2sock(127.0.0.1:${dns_listen_port}${dns2sock_cache})${dns2socks_socks_server:-127.0.0.1:9050} -> ${dns2socks_forward-D8.8.8.8:53}"
echolog " - 域名解析dns2socks..."
;;
https-dns-proxy)
xray_doh)
up_trust_doh_dns=$(config_t_get global up_trust_doh_dns "tcp")
if [ "$up_trust_doh_dns" = "socks" ]; then
use_tcp_node_resolve_dns=0
@ -812,17 +827,38 @@ start_dns() {
use_tcp_node_resolve_dns=1
msg="TCP节点"
fi
echolog " - 域名解析 https-dns-proxy(DOH)..."
up_trust_doh=$(config_t_get global up_trust_doh "https://dns.google/dns-query,8.8.4.4")
_doh_url=$(echo $up_trust_doh | awk -F ',' '{print $1}')
_doh_host_port=$(echo $_doh_url | sed "s/https:\/\///g" | awk -F '/' '{print $1}')
_doh_host=$(echo $_doh_host_port | awk -F ':' '{print $1}')
_doh_port=$(echo $_doh_host_port | awk -F ':' '{print $2}')
_doh_bootstrap=$(echo $up_trust_doh | cut -d ',' -sf 2-)
up_trust_doh_dns=$(config_t_get global up_trust_doh_dns "tcp")
if [ "$up_trust_doh_dns" = "socks" ]; then
socks_server=$(echo $(config_t_get global socks_server 127.0.0.1:9050) | sed "s/#/:/g")
socks_address=$(echo $socks_server | awk -F ':' '{print $1}')
socks_port=$(echo $socks_server | awk -F ':' '{print $2}')
lua $API_GEN_XRAY -dns_listen_port "${dns_listen_port}" -dns_server "${_doh_bootstrap}" -doh_url "${_doh_url}" -doh_host "${_doh_host}" -doh_socks_address "${socks_address}" -doh_socks_port "${socks_port}" > $TMP_PATH/DNS.json
ln_start_bin "$(first_type $(config_t_get global_app xray_file) xray)" xray $TMP_PATH/DNS.log -config="$TMP_PATH/DNS.json"
elif [ "${up_trust_doh_dns}" = "tcp" ]; then
DNS_FORWARD=""
_doh_bootstrap_dns=$(echo $_doh_bootstrap | sed "s/,/ /g")
for _dns in $_doh_bootstrap_dns; do
_dns=$(echo $_dns | awk -F ':' '{print $1}'):${_doh_port:-443}
[ -n "$DNS_FORWARD" ] && DNS_FORWARD=${DNS_FORWARD},${_dns} || DNS_FORWARD=${_dns}
done
lua $API_GEN_XRAY -dns_listen_port "${dns_listen_port}" -dns_server "${_doh_bootstrap}" -doh_url "${_doh_url}" -doh_host "${_doh_host}" > $TMP_PATH/DNS.json
ln_start_bin "$(first_type $(config_t_get global_app xray_file) xray)" xray $TMP_PATH/DNS.log -config="$TMP_PATH/DNS.json"
unset _dns _doh_bootstrap_dns
fi
unset _doh_url _doh_port _doh_bootstrap
echolog " - 域名解析 Xray DNS(DOH)..."
;;
pdnsd)
up_trust_pdnsd_dns=$(config_t_get global up_trust_pdnsd_dns "nil")
if [ "$up_trust_pdnsd_dns" = "udp" ]; then
use_udp_node_resolve_dns=1
msg="UDP节点"
elif [ "${up_trust_pdnsd_dns}" = "nil" ]; then
msg="TCP节点"
fi
echolog " - 域名解析pdnsd + 使用(${msg})解析域名..."
gen_pdnsd_config "${dns_listen_port}" "${pdnsd_forward}"
ln_start_bin "$(first_type pdnsd)" pdnsd "/dev/null" --daemon -c "${TMP_PATH}/pdnsd/pdnsd.conf" -d
echolog " - 域名解析pdnsd + 使用(TCP节点)解析域名..."
;;
udp)
use_udp_node_resolve_dns=1
@ -837,40 +873,7 @@ start_dns() {
}
;;
esac
if [ -n "$(echo ${DNS_MODE} | grep pdnsd)" ]; then
gen_pdnsd_config "${dns_listen_port}" "${pdnsd_forward}"
ln_start_bin "$(first_type pdnsd)" pdnsd "/dev/null" --daemon -c "${TMP_PATH}/pdnsd/pdnsd.conf" -d
fi
if [ -n "$(echo ${DNS_MODE} | grep 'https-dns-proxy')" ]; then
up_trust_doh=$(config_t_get global up_trust_doh "https://dns.google/dns-query,8.8.8.8,8.8.4.4")
_doh_url=$(echo $up_trust_doh | awk -F ',' '{print $1}')
_doh_port=$(echo $_doh_url | sed "s/:\/\///g" | awk -F ':' '{print $2}'| awk -F '/' '{print $1}')
_doh_bootstrap=$(echo $up_trust_doh | cut -d ',' -sf 2-)
up_trust_doh_dns=$(config_t_get global up_trust_doh_dns "tcp")
if [ "$up_trust_doh_dns" = "socks" ]; then
socks_server=$(echo $(config_t_get global socks_server 127.0.0.1:9050) | sed "s/#/:/g")
ln_start_bin "$(first_type https-dns-proxy)" https-dns-proxy "/dev/null" -a 127.0.0.1 -p "${dns_listen_port}" -b "${_doh_bootstrap}" -r "${_doh_url}" -4 -t socks5h://${socks_server}
elif [ "${up_trust_doh_dns}" = "tcp" ]; then
DNS_FORWARD=""
_doh_bootstrap_dns=$(echo $_doh_bootstrap | sed "s/,/ /g")
for _dns in $_doh_bootstrap_dns; do
_dns=$(echo $_dns | awk -F ':' '{print $1}'):${_doh_port:-443}
[ -n "$DNS_FORWARD" ] && DNS_FORWARD=${DNS_FORWARD},${_dns} || DNS_FORWARD=${_dns}
done
ln_start_bin "$(first_type https-dns-proxy)" https-dns-proxy "/dev/null" -a 127.0.0.1 -p "${dns_listen_port}" -b "${_doh_bootstrap}" -r "${_doh_url}" -4
unset _dns _doh_bootstrap_dns
fi
unset _doh_url _doh_port _doh_bootstrap
fi
if [ -n "$(echo ${DNS_MODE}${up_trust_pdnsd_dns} | grep dns2socks)" ]; then
local dns2socks_socks_server=$(echo $(config_t_get global socks_server 127.0.0.1:9050) | sed "s/#/:/g")
local dns2socks_forward=$(get_first_dns DNS_FORWARD 53 | sed 's/#/:/g')
[ "$DNS_CACHE" == "0" ] && local dns2sock_cache="/d"
ln_start_bin "$(first_type dns2socks)" dns2socks "/dev/null" "$dns2socks_socks_server" "$dns2socks_forward" "127.0.0.1:$dns_listen_port" $dns2sock_cache
echolog " - dns2sock(127.0.0.1:${dns_listen_port}${dns2sock_cache})${dns2socks_socks_server:-127.0.0.1:9050} -> ${dns2socks_forward-D46.182.19.48:53}"
#[ "$CHINADNS_NG" = "1" ] && [ -n "${global}${chnlist}" ] && [ -z "${returnhome}" ] && TUN_DNS=$(echo "${dns_listen_port}" | sed 's/:/#/g')
fi
[ "${use_udp_node_resolve_dns}" = "1" ] && echolog " * 要求代理 DNS 请求,如上游 DNS 非直连地址,确保 UDP 代理打开,并且已经正确转发!"
[ "${use_tcp_node_resolve_dns}" = "1" ] && echolog " * 请确认上游 DNS 支持 TCP 查询,如非直连地址,确保 TCP 代理打开,并且已经正确转发!"
}
@ -904,10 +907,6 @@ add_dnsmasq() {
#始终用国内DNS解析直连白名单列表
fwd_dns="${LOCAL_DNS}"
#如果使用ChinaDNS-NG则直接交给它处理
[ "$CHINADNS_NG" = "1" ] && unset fwd_dns
#如果没使用chnlist直接使用默认DNS
[ "${USE_CHNLIST}" = "0" ] && unset fwd_dns
sort -u "${RULES_PATH}/direct_host" | gen_dnsmasq_items "whitelist" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/00-direct_host.conf"
echolog " - [$?]域名白名单(whitelist)${fwd_dns:-默认}"

View File

@ -35,7 +35,8 @@ dst() {
}
comment() {
echo "-m comment --comment '$1'"
local name=$(echo $1 | sed 's/ /_/g')
echo "-m comment --comment '$name'"
}
RULE_LAST_INDEX() {
@ -222,7 +223,7 @@ load_acl() {
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && $ipt_m -A PSW $(comment "默认") -p udp -m multiport --dport $UDP_NO_REDIR_PORTS -j RETURN
[ "$UDP_NODE" != "nil" ] && {
msg="UDP默认代理使用UDP节点 [$(get_action_chain_name $UDP_PROXY_MODE)](TPROXY:${UDP_REDIR_PORT})代理"
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && msg="${msg}${TCP_NO_REDIR_PORTS}外的"
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && msg="${msg}${UDP_NO_REDIR_PORTS}外的"
msg="${msg}所有端口"
$ipt_m -A PSW $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_SHUNTLIST) $(REDIRECT $UDP_REDIR_PORT TPROXY)
$ipt_m -A PSW $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST) $(REDIRECT $UDP_REDIR_PORT TPROXY)
@ -311,14 +312,21 @@ filter_node() {
elif [ "$proxy_protocol" == "_shunt" ]; then
#echolog " - 按请求目的地址分流(${proxy_type}..."
local default_node=$(config_n_get $proxy_node default_node nil)
filter_rules $default_node $stream
local default_proxy=$(config_n_get $proxy_node default_proxy 0)
if [ "$default_proxy" == 1 ]; then
local main_node=$(config_n_get $proxy_node main_node nil)
filter_rules $main_node $stream
else
filter_rules $default_node $stream
fi
:<<!
local default_node_address=$(get_host_ip ipv4 $(config_n_get $default_node address) 1)
local default_node_port=$(config_n_get $default_node port)
local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
for shunt_id in $shunt_ids; do
local shunt_proxy=$(config_n_get $proxy_node "${shunt_id}_proxy" 0)
#local shunt_proxy=$(config_n_get $proxy_node "${shunt_id}_proxy" 0)
local shunt_proxy=0
local shunt_node=$(config_n_get $proxy_node "${shunt_id}" nil)
[ "$shunt_node" != "nil" ] && {
[ "$shunt_proxy" == 1 ] && {

View File

@ -426,6 +426,8 @@
43.228.148.0/22
43.228.152.0/22
43.228.188.0/22
43.228.204.0/22
43.228.240.0/22
43.229.40.0/22
43.229.48.0/22
43.229.56.0/22
@ -2538,6 +2540,7 @@
103.41.0.0/22
103.41.16.0/22
103.41.52.0/22
103.41.116.0/22
103.41.140.0/22
103.41.148.0/22
103.41.152.0/22
@ -2818,6 +2821,8 @@
103.56.60.0/22
103.56.72.0/22
103.56.76.0/22
103.56.100.0/22
103.56.104.0/22
103.56.140.0/22
103.56.152.0/22
103.56.184.0/22
@ -3916,7 +3921,6 @@
103.142.96.0/23
103.142.102.0/23
103.142.122.0/23
103.142.126.0/24
103.142.128.0/23
103.142.140.0/23
103.142.154.0/23
@ -4116,6 +4120,9 @@
103.161.14.0/23
103.161.102.0/23
103.161.138.0/23
103.161.208.0/23
103.161.220.0/23
103.161.254.0/23
103.192.0.0/22
103.192.4.0/22
103.192.8.0/22

View File

@ -34,7 +34,6 @@
2001:df0:d180::/48
2001:df0:d880::/48
2001:df1:c80::/48
2001:df1:4180::/48
2001:df1:4580::/48
2001:df1:5280::/48
2001:df1:5b80::/48
@ -1895,6 +1894,7 @@
2409:8000::/20
240a:2000::/24
240a:4000::/21
240a:6000::/24
240a:8000::/21
240a:c000::/20
240b:8000::/21

View File

@ -163,6 +163,20 @@ do
ucic2:set(application, node_id, "default_node", server)
end
}
local main_node_id = node.main_node
local main_node
if main_node_id then
main_node = ucic2:get_all(application, main_node_id)
end
CONFIG[#CONFIG + 1] = {
log = false,
currentNode = main_node,
remarks = "分流默认前置代理节点",
set = function(server)
ucic2:set(application, node_id, "main_node", server)
end
}
elseif node.protocol and node.protocol == '_balancing' then
local node_id = node[".name"]
local nodes = {}
@ -340,10 +354,7 @@ local function processData(szType, content, add_mode)
result.remarks = base64Decode(params.remarks)
elseif szType == 'vmess' then
local info = jsonParse(content)
result.type = 'V2ray'
if api.is_finded("xray") then
result.type = 'Xray'
end
result.type = 'Xray'
result.address = info.add
result.port = info.port
result.protocol = 'vmess'

View File

@ -83,7 +83,7 @@ test_auto_switch() {
[ -n "$node_address" ] && [ -n "$node_port" ] && local curlx="socks5h://$node_address:$node_port"
else
local tmp_port=$(/usr/share/passwall/app.sh get_new_port 61080 tcp)
/usr/share/passwall/app.sh run_socks "$main_node" "127.0.0.1" "$tmp_port" "/var/etc/passwall/auto_switch.json" "10"
/usr/share/passwall/app.sh run_socks "auto_switch" "$main_node" "127.0.0.1" "$tmp_port" "/var/etc/passwall/auto_switch.json"
local curlx="socks5h://127.0.0.1:$tmp_port"
fi
sleep 10s

View File

@ -11,11 +11,13 @@ Subject: [PATCH] add filter-aaaa option
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -270,6 +270,7 @@ struct event_desc {
@@ -269,7 +269,8 @@
#define OPT_IGNORE_CLID 59
#define OPT_SINGLE_PORT 60
#define OPT_LEASE_RENEW 61
#define OPT_LAST 62
+#define OPT_FILTER_AAAA 63
-#define OPT_LAST 62
+#define OPT_FILTER_AAAA 62
+#define OPT_LAST 63
#define OPTION_BITS (sizeof(unsigned int)*8)
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )

View File

@ -1,57 +0,0 @@
#
# Copyright (C) 2007-2010 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=iperf
PKG_VERSION:=2.0.13
PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_HASH:=c88adec966096a81136dda91b4bd19c27aae06df4d45a7f547a8e50d723778ad
PKG_SOURCE_URL:=@SF/iperf2
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_LICENSE:=BSD-3-Clause
PKG_BUILD_PARALLEL:=1
PKG_CONFIG_DEPENDS:=CONFIG_IPERF_ENABLE_MULTICAST
include $(INCLUDE_DIR)/uclibc++.mk
include $(INCLUDE_DIR)/package.mk
define Package/iperf
SECTION:=net
CATEGORY:=Network
DEPENDS:= $(CXX_DEPENDS) +libpthread
TITLE:=Internet Protocol bandwidth measuring tool
URL:=http://sourceforge.net/projects/iperf2/
endef
define Package/iperf/description
Iperf is a modern alternative for measuring TCP and UDP bandwidth
performance, allowing the tuning of various parameters and
characteristics.
endef
TARGET_CFLAGS += -D_GNU_SOURCE
CONFIGURE_ARGS += --disable-multicast
ifeq ($(CONFIG_IPV6),)
CONFIGURE_ARGS += --disable-ipv6
endif
CONFIGURE_VARS += CXXFLAGS="$$$$CXXFLAGS -fno-rtti"
CONFIGURE_VARS += LIBS="-lpthread -lm"
define Package/iperf/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/iperf $(1)/usr/bin/iperf
endef
$(eval $(call BuildPackage,iperf))

Some files were not shown because too many files have changed in this diff Show More