首页
留言
动态
归档
推荐
工具
Search
1
微信-域名被封监测以及自动更换被封域名
7,444 阅读
2
逗比根据地打不开,doub.io无法解析,最新逗比根据地镜像地址
6,398 阅读
3
广告投放,广告收入
6,332 阅读
4
shadowsocksR科学上网
5,496 阅读
5
laravel nova 权限管理工具
5,026 阅读
随便写写
科学上网
Web开发
瞎折腾
Search
标签搜索
quantumultx
laravel
openwrt
jd_scripts
oh-my-zsh
web开发环境
ubuntu
nginx
laravel nova
google adsense
京东签到
薅羊毛
laradock
撸羊毛
xdebug
ios14 beta
xtls
oh my zsh
Vue
phpstorm
orzlee
累计撰写
39
篇文章
累计收到
253
条评论
首页
栏目
随便写写
科学上网
Web开发
瞎折腾
页面
留言
动态
归档
推荐
工具
搜索到
39
篇与
orzlee
的结果
2021-04-13
Nginx SNI 分流(端口复用)使用Xray+VLESS+XTLS
前言 Xray已经出来一段时间了,之前一直使用VLESS+tls+ws方式科学上网,其实都够用,没什么问题。但是了解了下XTLS黑科技,再看看Xray性能测试,这货简直爆炸,性能是TLS的数倍。 其实之前折腾过一次,但是Xray要监听443端口(不监听也行,但是不完美啊),影响做站。虽然有解决方法,但是不够完整,我一不小心就跳坑里面去了。Xray已经带了SNI回落功能(教程看这里:通过 SNI 回落功能实现伪装与按域名分流),Nginx也带SNI功能,我还是觉得用Nginx的比较好,免得折腾Xray影响网站运行。 这里我不会写如何安装Xray,因为教程实在是太多了,嫌麻烦还有一键脚本:Xray_onekey(V2ray脚本别用这个作者的哈,特别是服务器有站点的!!!Xray脚本这个大佬的还不错)。 坑 因为服务器上有几个站点,装完Xray后实现SNI分流,过程非常顺利,但是chrome上有问题,几个二级域名访问的内容全部和第一个访问的域名一样。 例如:我先访问 a.example.com 然后在访问 b.example.com,b.example.com 响应内容和 a.example.com 一模一样,然后再访问 c.example.com 还是和 a.example.com 一样。开chrome隐身模式直接访问 c.example.com 正常,然后访问 a.example.com 或 b.example.com 内容又全是 c.example.com 的(不一定会每次都这样,要看浏览器是否使用现有连接或服务器是否断开了之前的连接)。 这个问题折腾我很长时间,最后发现和HTTP/2有关,我所有站点不使用HTTP/2就会正常,只要有一个站点使用了HTTP/2,你先访问HTTP/2站点,那么后面的其他子域名都会变成它的内容。 最开始我使用Xray的SNI也是这样,我还以为是Xray SNI的问题,之后换成Nginx使用SNI还是这样。chrome中有这个问题,用手机safari浏览器完全正常。 经过网上一番搜刮,终于找到了问题根源:通配符域名证书。 用下人家的图(原作者文章:Multiplex TLS Traffic with SNI Routing): *由于原始服务器10.0.3.2使用的TLS证书具有通配符名称 .example.com,因此Web浏览器可以建立服务器名称为 b.example.com 的 TLS连接,并对HTTP/2请求使用相同的连接到 a.example.com。这可能会在网站和应用程序中导致未定义的行为。** 因为HTTP/2会保持TCP连接,导致你访问了 a.example.com 后,在访问 b.example.com 的时候使用的同一个连接,SNI跟失效了一样,直接使用该连接访问之前的服务。我在Xray的调试日志中发现访问错误的域名没有获取到,是空的! 两个域名使用同一个连接(红框内是连接ID),可以很清楚的看到两个域名使用同一个连接,返回的内容也是一模一样: 解决办法两种: 不使用HTTP/2。 不使用通配符域名证书,站点域名证书一个个申请。 配置Nginx SNI 使用Nginx首先得安装(如果服务器自带就不用折腾了),不会安装Nginx可以看我之前的文章:Ubuntu 安装nginx(如果使用Xray_onekey脚本,那他已经帮你全部弄好了,你都不用折腾)。 nginx.conf配置追加: stream { map $ssl_preread_server_name $orzlee { a.example.com a; b.example.com b; c.example.com c; } upstream a { server 127.0.0.1:60088; ### A站点监听端口,xray xtls伪装站点 } upstream xtls { server 127.0.0.1:4443; ### 你的Xray端口 } upstream b { server 127.0.0.1:60001; ### B站点监听端口,业务站点 } upstream c { server 127.0.0.1:60002; ### C站点监听端口,业务站点 } server { listen 443 reuseport; listen [::]:443 reuseport; proxy_pass $orzlee; ssl_preread on; proxy_protocol on; } server { ### Xray XTLS listen 127.0.0.1:60088 proxy_protocol; proxy_pass xtls; } } a.example.com.conf配置(伪装站点): server { listen 80; listen [::]:80; server_name a.example.com; return 301 https://$http_host$request_uri; } server { ### 伪造站点由Xray处理SSL listen 127.0.0.1:60003 proxy_protocol; ### xray http/1.1 listen 127.0.0.1:60004 http2 proxy_protocol; ### xray http/2 set_real_ip_from 127.0.0.1; real_ip_header proxy_protocol; port_in_redirect off; ###重定向去掉端口号 server_name a.example.com; index index.html index.htm index.php default.php default.htm default.html; root /var/www/a.example.com; ... } b.example.com.conf配置(其他业务站点配置照葫芦画瓢): server { listen 80; server_name b.example.com; rewrite ^(.*) https://b.example.com$1 permanent; } server { listen 127.0.0.1:60001 proxy_protocol ssl http2; set_real_ip_from 127.0.0.1; ### 获取真实客户IP,不然全是127.0.0.1 real_ip_header proxy_protocol; port_in_redirect off; ###重定向去掉端口号。不然类似 try_files nginx帮你重定向时,你浏览器上都带了60003这样的端口 ssl_certificate b.example.com.cer; ### 证书换成你的 ssl_certificate_key b.example.com.key; ### 证书换成你的 server_name b.example.com; root /var/www/b.example.com; index index.php index.html index.htm; ... } 配置Xray 服务端配置: { "log": { "access": "/var/log/xray/access.log", "error": "/var/log/xray/error.log", "loglevel": "warning" }, "inbounds": [ { "listen": "127.0.0.1", "port": 4443, "protocol": "vless", "settings": { "clients": [ { "id": "你的UUID", "flow": "xtls-rprx-direct" } ], "decryption": "none", "fallbacks": [ { "dest": 60003, "xver": 1 }, { "dest": 60004, "alpn": "h2", "xver": 1 } ] }, "streamSettings": { "network": "tcp", "security": "xtls", "xtlsSettings": { "alpn": [ "h2", "http/1.1" ], "minVersion": "1.3", "certificates": [ { "certificateFile": "b.example.com.cer 记得换证书", "keyFile": "b.example.com.key 记得换证书" } ] } }, "sniffing": { "enabled": true, "destOverride": [ "http", "tls" ] } } ], "outbounds": [ { "protocol": "freedom" } ] } 客户端看作者说明吧,值得一看:Outbounds 可用协议列表-VLESS,flow仔细看看。 结语 本来折腾Xray的,结果Nginx折腾大半天。虽然掉坑里了,总算是爬出来了,受益匪浅! 通配符证书用起来省事,碰到坑了一下还不好找问题。就今天这个坑上网找都不知道怎么描述,基本上找不到相关问题,比较冷门。之前参考其他博主Nginx SNI配置发现有其他同学也有这样的问题,但是无从查起,不了了之! 遇到这个坑不长记性都难。
2021年04月13日
7 阅读
0 评论
0 点赞
2021-03-14
openwrt-安装oh-my-zsh
前言 openwrt的shell连上次会话历史记录都没有,很是蛋疼。不如换成oh-my-zsh,还有很多插件可以玩。 VPS上安装可以看之前的文章:oh-my-zsh强大的zsh配置管理 安装 操作前记得备份你得openwrt配置,现在很多用的都是改版openwrt,不确定会发生什么奇奇怪怪的问题,但是大部分是没有问题的,备份一下保险。 登陆到openwrt ssh,首先安装依赖: opkg update && opkg install wget unzip zsh ca-certificates 安装oh-my-zsh: sh -c "$(wget -O- https://raw.githubusercontent.com/felix-fly/openwrt-ohmyzsh/master/install.sh)" 这时候已经安装完成了,还差设置默认shell为zsh: which zsh && sed -i -- 's:/bin/ash:'`which zsh`':g' /etc/passwd 到此结束,退出当前会话然后重新登陆ssh看看是不是已经默认为zsh了。 有了历史记录再配合命令补全、命令高亮插件简直不能太爽!!! 自动补全插件或其他插件安装方法还是请看:oh-my-zsh强大的zsh配置管理 自动补全插件: 命令高亮插件: 如果你要卸载oh-my-zsh的话: sh -c "$(wget -O- https://raw.githubusercontent.com/felix-fly/openwrt-ohmyzsh/master/uninstall.sh)" 结语 装完oh-my-zsh感觉没有束缚了,这样的终端爽的飞起。之前所有的服务器都装了oh-my-zsh,习惯了,没有oh-my-zsh总感觉太单调了,敲起来不顺手。
2021年03月14日
107 阅读
0 评论
0 点赞
openwrt-通过telegram bot自动创建启动jd-scripts docker容器
2021年03月13日
415 阅读
8 评论
0 点赞
2021-03-13
前言 使用lxk0301大佬的jd_scripts-docker脚本后突发奇想,如果利用telegram bot获取用户京东cookie,然后自动创建docker容器并且启动容器跑脚本,这个流程一气呵成,以后京东cookie过期就可以很方便的处理,然后自己朋友也可以扫京东登陆二维码就部署整个签到脚本了。 在openwrt折腾可以看我之前的文章:openwrt-docker部署lxk0301京东自动签到脚本 2021-03-22更新:作者已经更新docker容器,详细说明:增加bot交互,spnode指令。容器已经自带telegram bot,大量与docker容器配套的命令以及获取cookie功能。有兴趣可以玩玩看。 运行环境和思路 我使用的是openwrt软路由(CPU J4105, 8G, 128G SSD),由于性能过剩,不折腾点东西不舒服,所以没有放VPS上。软路由固件使用的是eSir大佬的高大全版本,eSir大佬固件盘。记得扩容overlay分区,然后opt容量也要注意下,我在openwrt-docker部署lxk0301京东自动签到脚本文章中提到过。 由于部署在路由器上,telegram bot webhook发到路由可能会遇到GFW的干扰(不确定是否会干扰入境流量,可以试试看),我使用frp(eSir openwrt自带)做内网穿透,frp服务端需挂在境外服务器上,这样外网问题就能解决。但是路由器还是需要科学上网的。 telegram bot开发使用python,还有少部分lua,因为openwrt上的dockerman插件语言也是lua语言,启动docker时还是希望能在dockerman中管理,所以还是折腾了lua。 整个流程: 用户在telegram bot发送命令 telegram bot返回一个京东登陆二维码(以下图片中的login命令是测试时候的) 用户扫码二维码,服务器获取用户京东cookie 服务器拿到cookie创建(或删除重建)一个jd_scripts-docker容器,并且启动 提示用户启动成功或失败 成功后可以在openwrt web端docker-容器看到新加入的用户docker容器,还可以在openwrt的dockerman插件中管理容器。 思路: 用户发送命令给telegram bot,服务器接收到后进入配置好的容器,执行/scripts/getJDCookies.js脚本获取脚本生成的京东登陆链接,用链接生成二维码,通过telegram bot返回给用户。二维码有效期三分钟,脚本也会持续三分钟。用户扫码后服务器会捕获到脚本回显,提取京东cookie。 拿到cooki后判断用户是否已经创建容器,创建了多久,超过N天的删除旧容器,然后再创建一个新的容器启动,没有使用过的用户直接创建一个新的。由于我想兼容dockerman,所以用lua语言折腾了一个简版创建和管理docker命令行脚本。懒得折腾了,服务器直接复制一份已存在的jd_scripts-docker脚本配置新建,环境变量和脚本可以自行配置就行了。启动成功捕获命令行回显容器ID,容器ID和用户信息,京东cookie存Sqlite数据库。 由于防止用户频繁提交,使用reids存下已经获取二维码的telegram用户ID,必须等待三分钟或者jd_scripts-docker成功后再次获取。 本来是想使用一个容器,然后在容器里面修改JDCOOKIE环境变量,配置多个cookie。但是目前有两个缺点: 单容器多用户跑脚本时会一个个跑,并不是并发跑,人数一多脚本执行时间会很长(如果限制单容器用户人数也许是个办法,比如说一个容器只允许5个用户,多出来的再建个新容器,以后再说吧!)。 脚本通知(多账号)只能发给一个环境变量配置好的接收用户。 不过最近lxk0301大佬更新了单容器多用户脚本会自动互助的功能,只能自己再想办法折腾下了。 脚本说明: 2021-03-16更新:添加单容器追加cookie功能,这样VPS应该能用了(我没有测试,但是不涉及到dockerman容器管理应该是没有问题的!): 仓库地址:Github env.config文件添加两个配置,主要是add_user_mode添加用户模式,默认是create,单容器是attach: [telegram_bot] ... [jd_scripts] ... auto_delete_docker_by_days=30 //目前没有实现自动删除过期用户容器功能,只是attach模式中过滤超过N天的用户cookie add_user_mode=attach //创建容易方式:attach 附加,create 创建,附加只会追加cookie到existed_docker_container_name配置容器里,create每一个用户都会创建一个新的docker容器 [sqlite] ... 如果使用attach模式,会在当前目录生成一个cookies.sh文件,执行该文件会导入所有通过telegram bot加入的有效用户cookie到环境变量。 使用attach模式方法: 现在开始准备新建一个容器,挂载cookies.sh文件到jd_scripts_docker容器(export_jd_cookies_script_orz.sh挂载文件名要改的话下面的脚本内容也要跟着修改): 你的目录/cookies.sh:/scripts/docker/export_jd_cookies_script_orz.sh 添加一个自定义脚本: 先挂载本地脚本(名称目录自定,但是挂载后的不要改了,不然又要改脚本内容。如果远程脚本就不用挂载了): 你的目录/docker_shell.sh:/scripts/docker/docker_shell.sh 添加环境变量(远程脚本不用上面的挂载docker_shell.sh步骤): CUSTOM_SHELL_FILE=/scripts/docker/docker_shell.sh 脚本内容,意思是每分钟执行update_crontab.sh脚本: if ! [ ! -f "/scripts/docker/export_jd_cookies_script_orz.sh" ]; then echo "* * * * * sh +x /scripts/docker/update_crontab.sh 2>&1" >> /scripts/docker/merged_list_file.sh fi 挂载update_crontab.sh脚本 你的目录/update_crontab.sh:/scripts/docker/update_crontab.sh 脚本内容: FIND_FILE="/scripts/docker/merged_list_file.sh" FIND_STR="export_jd_cookies_script_orz.sh" # merged_list_file.sh定时任务加入cookies环境变量脚本 if ! [ `grep -c "$FIND_STR" $FIND_FILE` -ne '0' ];then sed -i 's/\/scripts\/logs\/auto_help_export\.log/\/scripts\/logs\/auto_help_export\.log \&\& \. \/scripts\/docker\/export_jd_cookies_script_orz\.sh/g' $FIND_FILE ## 更新定时任务列表 crontab $FIND_FILE fi CRZAY_JOY_COIN_FILE="/scripts/docker/proc_file.sh" # joy coin脚本加入cookies环境变量脚本 if ! [ `grep -c "$FIND_STR" $CRZAY_JOY_COIN_FILE` -ne '0' ];then sed -i 's/node \/scripts\/jd_crazy_joy_coin\.js/\. \/scripts\/docker\/export_jd_cookies_script_orz\.sh \&\& node \/scripts\/jd_crazy_joy_coin\.js/g' $CRZAY_JOY_COIN_FILE sh -x /scripts/docker/proc_file.sh fi 该脚本主要是每分钟执行,但是只修改一次merged_list_file.sh定时任务文件,并且立即更新crontab list,为每个京东任务定时脚本执行前先更新JD_COOKIE环境变量,这样你得脚本执行才能正确获取cookie。第二个是joy coin脚本,这个脚本没有在定时任务列表中,每天只会执行一次,所以要单独修改后并启动。 因为是每分钟执行,所以可以很大程度上避免cookie没有导入的尴尬。 你过你还需要其他环境变量或者磁盘挂载记得自己加。 单容器只有创建容器时配置好的通知环境变量接收通知,没法多个用户分发的。而且人数一多执行单个脚本时间会延长。优点就是可以添加环境变量配置ENABLE_AUTO_HELP=true开启单容器多用户互助。 2021-03-16更新结束。 脚本地址:jd_scripts telegram bot python3.8, python3.9都没问题,其他环境没测试,我使用python3.9开发,openwrt上是3.8没有发现问题。 openwrt上安装pip请点击get-pip。 之前python用的qrcode包生成二维码,但是默认只有svg格式,想生成png,jpg就需要Pillow包,但是这个包在openwrt上安装一直报错,确少zlib库,这个好解决,安装zlib-dev就好了,然后又提示缺少jpeg,这个库openwrt已经用libjpeg-turbo替换了libjpeg库,就算安装了libjpeg-turbo也还是不行,所以换成segno包了。 需要安装包(不知道是不是有遗漏): pip install segno python-telegram-bot peewee redis 脚本已经撸出来了,做个说明吧!自己用也没太多讲究(记得删除注释): [telegram_bot] token = 88888888:AAAAAAAAAAAAAAAA //这是telegram bot token port = 8080 //监听端口, frp请填写web端本地端口(local_port),openwrt别配置80端口,不然都无法启动telegram脚本,因为openwrt web端已经占用了80端口 admins=88888888,8888888 //管理员用户,如果指定了管理员就只能管理员使用京东docker命令,获取自己的userid看这里https://gitee.com/lxk0301/jd_docker/blob/master/backUp/TG_PUSH.md url=https://telegram.bot/ // telegram bot webhook发送域名 redis_cache_prefix=telegram_bot: //redis缓存前缀,可以随便改 commands=jd_script_start:登陆京东并且创建docker容器 //命令,可以自行添加,命令格式 命令:命令说明,命令:命令说明,命令:命令说明 多命令逗号隔开 [jd_scripts] existed_docker_container_name = jd_scripts_orzlee //已经创建好的容器名称,主要用于执行`/scripts/getJDCookies.js`脚本给用户登陆 existed_docker_container_id=1919c3ff9e45ee6d1ca58xxxxxxxxxxxxxx5a8d //已经创建好的容器id,主要用于复制配置文件 docker_container_prefix = jd_scripts_ //新建docker容器名称前缀 tg_bot_token=88888888:AAAAAAAAAAAAAAAA //jd_scirpts 脚本推送通知bot token,可以和上面一样,可以使用其他token,推送用户就是谁请求的二维码,通知就会推送给谁 min_login_days=10 //最少登陆多少天才能重新使用,这个是怕已经成功创建容器后,用户一直用同一个京东账户扫码,然后服务器不停的删除容器创建容器,单位是天,可自行修改,0就是不设置 max_docker_num=50 //最大用户数量,这是判断Sqlite数据库用户数量决定的,不是你本地docker容器数量 auto_delete_docker_by_days=30 //目前没有实现自动删除过期用户容器功能,只是attach模式中过滤超过N天的用户cookie add_user_mode=attach //创建容易方式:attach 附加,create 创建,附加只会追加cookie到existed_docker_container_name配置容器里,create每一个用户都会创建一个新的docker容器 [sqlite] database=telegram_bot_jd_scripts.db //数据库文件名称 环境变量和挂载我给写死了,需要自己修改下吧! 命令由于有"号,所以要转义,在shell中要转义\",代码中就必须转义\和",所以环境变量和挂载磁盘都需要\\\"环境变量=xxx(挂载参数:xxx)\\\"包含起来,因为这个基本不会改变,所以没有放入配置文件,你可以继续加或者删掉部分,像JDCOOKIE和TG_USER_ID这些都是用户的变量,所以还是留下吧: from src.config import * from src import common def createAndStartContainer(cookie, tgUserId, name): ##lua newcontainer.lua -n jd_scripts_test -e \"JD_COOKIE=pt_key=AAJgSIA0ADC-1mV_7uCjZK2kIBxYN4sdb1L9PyAktQewf5Hse7QHaFJVBE3egdRZugQF0FeiWvI\;pt_pin=fangxueyidao\;\",\"RANDOM_DELAY_MAX= ##600\",\"TG_BOT_TOKEN=644204874\:AAETxq7Wr2-rXEijjKYJqn3vXsCijG6xm-w\",\"TG_USER_ID=490884842\",\"CUSTOM_SHELL_FILE=https://raw.githubusercontent.com/jianminLee/jd_scripts/main/docker_shell.sh\" -m \"/opt/jd_scri ##pts/logs:/scripts/logs\" ## 拼接参数 n = env['jd_scripts']['docker_container_prefix'] + name e = '\\\"JD_COOKIE='+cookie.strip()+'\\\",\\\"RANDOM_DELAY_MAX=600\\\",\\\"TG_BOT_TOKEN=' \ +env['jd_scripts']['tg_bot_token'] \ +'\\\",\\\"TG_USER_ID='+str(tgUserId)+'\\\"' m = '\\\"/opt/jd_scripts/logs/'+ str(tgUserId) +':/scripts/logs\\\"' command = ("cd "+ os.path.abspath('lua/') +" && lua "+ os.path.abspath('lua/dockerman.lua') +" -n " + n + ' -e ' + e + ' -m ' + m + ' -d ' + env['jd_scripts']['existed_docker_container_id']).replace(';','\\;') print(n+'\n'+e+'\n'+m+'\ncommand:'+command) result = common.run_command(command) for res in result: if res.startswith('id:'): #返回容器ID return res[3:] return -1 def stopAndDeleteContainer(containerId): command = 'cd '+os.path.abspath('lua/')+' && lua '+os.path.abspath('lua/dockerman.lua')+' -D '+containerId result = common.run_command(command) for res in result: if res == 0: #返回容器ID return 0 return -1 lua管理docker命令参数说明: { "-m, --mount", help = "容器挂载目录" }, { "-d, --duplicate", help = "容器ID 复制容易配置,复制后依然可以使用其他选项覆盖" }, { "-D, --delete", help = "容器ID 删除容器" }, { "-n, --name", help = "容器名称" }, { "-e, --env", help = "容器环境变量" }, 运行的话使用python serve.py。 frp服务配置 eSir的openwrt高大全版本固件中服务-frp内网穿透可以看到frp工具(服务器下面的端口是1234,和frps.ini中的bind_port一致): 添加一个客户端,自定义域名随便起,不用注册,内网使用: 服务器安装可以看之前的文章frp内网穿透,但是我这里使用nginx反向代理安装。 frps.ini配置: [common] bind_port = 1234 vhost_http_port = 8080 token = AAAAAAAAAA type = http custom_domains = orzlee.test //这个域名和客户端自定义域名一致 nginx反向代理配置: server { listen 80; server_name 你的域名; ###rewrite ^(.*) https://$server_name$1 permanent; charset utf-8; location / { proxy_pass http://127.0.0.1:8080; ##端口是frps.ini中的vhost_http_port端口 proxy_set_header Host orzlee.test; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; } ##location = /favicon.ico { access_log off; log_not_found off; } ##location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log off; sendfile off; location ~ /\.ht { deny all; } } server { listen 443 ssl http2; server_name 你的域名; ssl_certificate 证书目录/xxx.cer; ssl_certificate_key 证书私钥xxx.key; ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; #屏蔽不安全的加密方式 ssl_prefer_server_ciphers on; index index.html index.htm index.php; charset utf-8; client_max_body_size 5M; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host orzlee.test; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; } ##location = /favicon.ico { access_log off; log_not_found off; } ##location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log off; sendfile off; location ~ /\.ht { deny all; } } 这样frp就通了,然后本地telegram-bot就可以接收webhook通知了。 结语 后续还有很多需要实现的功能,例如自动删除一个月以后的docker容器,因为可能cookie过期了,再继续跑下去也没有什么意义,还占用资源。等之后有时间在弄吧,折腾这个把openwrt弄挂了,还好有备份!
2021-03-03
LXK0301京东签到脚本-京喜工厂解决无法签到异常
前言 LXK0301大佬的京喜工厂自动签到脚本不知怎么一直提示:亲,活动太火爆了,请稍后再试吧!,基本无法使用,任务也不自动做了。 上网查了一下,全是说黑号,真蛋疼。因为脚本无法做任务什么的,但是手动完全没有问题,根本不是黑号,网上一股脑说黑号。 我就不信邪,app能做任务脚本就不行,肯定是脚本有问题。 2021-03-25 第二次更新,已经不需要自己抓包获取签名参数了,脚本会在每次执行时自动获取签名参数。已经联系作者,等作者更新吧!(推荐使用作者脚本,修复了参团问题) 2021-03-25更新,今天更新了下脚本,应该可以获取自己的签名参数使用了,有时间的朋友可以测试一下!仓库地址:jd_scripts-orzlee 2021-03-23更新,自己获取签名的方法可能无效,作者已经跟新脚本,目前使用我提供的签名参数可以正常做任务和领取电力,后续可能还需要研究。更新作者脚本即可! 原因 最根本的原因就是脚本发送请求链接签名有问题,这个好像只针对了部分用户,有的用户没问题,有的就会一直提示:亲,活动太火爆了,请稍后再试吧!。 起初发现问题是在手机上用QuantumultX抓包京喜APP,点击地上的零件,再抓包脚本,然后找出usermaterial/PickUpComponent请求来对比。开始我还以为是cookie问题,我替换cookie重试请求还是太火爆错误,再重发一下抓包京喜APP的请求,依然成功。再替换替换脚本请求的url参数为抓包app的,莫名奇妙的成功了。这个锅必须脚本背了! 脚本中decrypt函数是负责请求链接签名的,但是目前脚本有问题,很多签名key都是没有值的,因为根本没有获取值,只有少部分定义了默认值。来看一下代码(目前是1535行): function decrypt(time, stk, type) { if (stk) { const random = 'pmUmA8IyRcDp'; //这些常量其实每个用户都可能不一样 const token = `tk01wd4571d58a8nT0tkdXczeW94f5x4qjWs44kcPCTXeWKa2xXY+ZxHaOtbRxmyw6vrIF4RDFwwTUfwy1pIqNE0oyWW`; //这些常量其实每个用户都可能不一样 const fingerprint = 8410347712257161; //这些常量其实每个用户都可能不一样 //这个时间转换和现在的不一样,现在是new Date(time).Format("yyyyMMddhhmmssSSS");,转换结果不一样,加密出来也不一样 const timestamp = new Date(time).Format("yyyyMMddhhmmssS"); const appId = 10001; //这个是活动id 是固定的 const str = `${token}${fingerprint}${timestamp}${appId}${random}`; const hash1 = $.CryptoJS.HmacSHA512(str, token).toString($.CryptoJS.enc.Hex); //这里加密算法有可能不一样 let st = ''; stk.split(',').map((item, index) => { //下面的签名参数只有些默认值,很多都是空的,但是链接上又带了有效值,服务器验签估计不合法(但是有的用户却没有问题,搞不懂) st += `${item}:${item === '_time' ? time : item === 'zone' ? 'dream_factory' : item === 'type' ? type || '1' : ''}${index === stk.split(',').length -1 ? '' : '&'}`; }) const hash2 = $.CryptoJS.HmacSHA256(st, hash1).toString($.CryptoJS.enc.Hex); console.log(`st:${st}\n`) // console.log(`hash2:${JSON.stringify(["".concat(timestamp.toString()), "".concat(fingerprint.toString()), "".concat(appId.toString()), "".concat(token), "".concat(hash2)])}\n`) console.log(`h5st:${["".concat(timestamp.toString()), "".concat(fingerprint.toString()), "".concat(appId.toString()), "".concat(token), "".concat(hash2)].join(";")}\n`) return ["".concat(timestamp.toString()), "".concat(fingerprint.toString()), "".concat(appId.toString()), "".concat(token), "".concat(hash2)].join(";") } else { return '20210121201915905;8410347712257161;10001;tk01wa5bd1b5fa8nK2drQ3o3azhyhItRUb1DBNK57SQnGlXj9kmaV/iQlhKdXuz1RME5H/+NboJj8FAS9N+FcoAbf6cB;3c567a551a8e1c905a8d676d69e873c0bc7adbd8277957f90e95ab231e1800f2' } } 研究过程我就不再多说了,京东那边全是混淆的JS,真的很头疼,我弄了一下午才摸清楚他的逻辑。 整个流程大概是这样(官方的js混淆了,乱七八糟的就不贴代码了): 第一次进入活动页面会发送POST请求:https://cactus.jd.com/request_algo?g_ty=ajax,将返回结果储存在本地(这个默认应该没有有效期,但是京喜工厂里面的JS会设置有效期,过期会重新获取)。已经更新脚本自动获取签名参数了。 请求参数: { appId: "10001" expandParams: "" //fingerprint //pc浏览器我试过,就算拿到所有数据跑脚本依然不行,还是太火爆错误。所以保险还是去京喜APP抓包吧! fp: "5525701123405161" platform: "web" timestamp: 1614687205087 version: "1.0" } 接口会返回: { data: { result: { //加密函数 algo: "function test(token,fingerprint,timestamp,appId,algo){const random='jQ1SS0VI2Vuw';const str=`${token}${fingerprint}${timestamp}${appId}${random}`;return algo.SHA512(str)}" //加密token tk: "tk01w91541b51a8nWURUM3hiZk9HHRKep5j4FeOg/jHOQoGSDcsasdSOZ+83iz4uf/YBXHcK6xMIUqqv5/iJv6F0aooT5Nd3" } version: "1.0" message: "" status: 200 } } 这个接口会返回所有签名需要的参数,也就是脚本中decrypt中的参数,其实照着值样子都知道怎么替换了。 当前时间格式转换new Date(time).Format("yyyyMMddhhmmssSSS")这个时间是和链接参数中的'_time匹配'。 字符串拼接${token}${fingerprint}${timestamp}${appId}${random}。 第一次签名,将第三步的字符串用SHA或者MD5加密,这个主要参考第一步中的机密函数: function test(token,fingerprint,timestamp,appId,algo){ const random='jQ1SS0VI2Vuw'; const str=`${token}${fingerprint}${timestamp}${appId}${random}`; return algo.SHA512(str) } 这个函数提供了加密方法和随机字符串,官方直接用它做闭包函数第一次签名。 第一次签名完成后,开始第二次了,这个参数每个接口可能不同,它会按照请求url中的_stk参数来提供签名参数,例如&_stk=_time,pin,placeId,zone,那么就需要将参数拼接成time:xxxx&pin:xxxx&placeId:xxxx&zone:xxx这样子。stk参数的值也会包含在url中,例如: https://m.jingxi.com/dreamfactory/usermaterial/PickUpComponent?zone=dream_factory&placeId=1&pin=91DCBu8VvYt6rEdezHZ_VQ%3D%3D&_time=1614622722731&_stk=_time%2Cpin%2CplaceId%2Czone&_ste=1&h5st=20210302021842732%3B6099600123439161%3B10001%3Btk01wa66691cafa8nSmV1UDN2SWtZAiPI1uR1EAuPwYDaw36v9gQGhJz5Ac4h2cjfkeCQexVweqwa6%2BsjvERwkVU6wxTK%3Ba795we798qwe789789qe8262584d49f9449a1ce0194bb26c72049eef428f5e23e1043a641d&_=1614622722744&sceneval=2&g_login_type=1&callback=jsonpCBKR&g_ty=ls 第二次签名加密的算法是固定的,SHA256。 最后拼接: ["".concat(timestamp.toString()), "".concat(fingerprint.toString()), "".concat(appId.toString()), "".concat(token), "".concat(hash2)].join(";") 抓包 2021-03-04 更新可以免去抓包和修改脚本操作了: 一旦有一个设备的url签名参数更新,其他设备都会失效,如果多设备跑同一个账号要保持一直,否则还是会失败的!!! 我更新了脚本,不需要手动抓包了,QuantumultX可以添加url_sign_params.conf重写引用,其他平台可能需要自己写一下。然后删除京喜APP,重新下载后进入京喜工厂(最好重下APP,不然有可能还是太火爆异常,如果没有提示退出京喜工厂再进一次,多试试!): 折腾好了就只使用京喜APP进入京喜工厂(url签名参数会被京喜工厂里面的JS设置过期时间,过期会重新获取),以免从京东APP进入京喜工厂跳转到京喜APP重新获取覆盖,京东APP里面的京喜工厂获取的url签名参数也不能执行成功!只能使用京喜APP的url签名参数! 日志可以查看url签名参数: 以下为未更新之前的方法: 找到了问题就好解决了,抓包京喜APP一个请求就行了,抓包之前建议先删除APP,因为签名参数会存在本地,基本上弄不到了。删掉APP再进入京喜工厂之前,准备好抓包工具,IOS可以用QuantumultX、Surge等,PC抓包太多了,一搜一大把。 准备好抓包工具之后,进入京喜工厂,等待完全进入工厂,最好再捡下零件。没有报错就可以关掉抓包工具了。 搜索algo,找到签名参数请求: 请求JSON和响应JSON都要看,不然你不知道fingerprint参数,是一串数字,在请求JSON里: 复制返回请求中的参数: 修改脚本 脚本我修改了很多处,但是很简单: 新增一个获取url参数的函数: /** * 新增url参数获取函数 * @param url_string * @param param * @returns {string|string} */ function getUrlQueryParams(url_string, param) { let url = new URL(url_string); let data = url.searchParams.get(param); return data ? data : ''; } 时间函数与官方不一致,会导致签名结果错误(这函数是官方混淆JS里面扒出来的): /* 修改时间戳转换函数,京喜工厂原版修改 */ Date.prototype.Format = function (fmt) { var e, n = this, d = fmt, l = { "M+": n.getMonth() + 1, "d+": n.getDate(), "D+": n.getDate(), "h+": n.getHours(), "H+": n.getHours(), "m+": n.getMinutes(), "s+": n.getSeconds(), "w+": n.getDay(), "q+": Math.floor((n.getMonth() + 3) / 3), "S+": n.getMilliseconds() }; /(y+)/i.test(d) && (d = d.replace(RegExp.$1, "".concat(n.getFullYear()).substr(4 - RegExp.$1.length))); for (var k in l) { if (new RegExp("(".concat(k, ")")).test(d)) { var t, a = "S+" === k ? "000" : "00"; d = d.replace(RegExp.$1, 1 == RegExp.$1.length ? l[k] : ("".concat(a) + l[k]).substr("".concat(l[k]).length)) } } return d; } decrypt函数也要修改,我加了一个url参数,在拼接签名参数需要的值可以在url中拿(实在不想动太多代码,怎么方便怎么来吧): /* 签名函数 签名信息获取地址:https://cactus.jd.com/request_algo?g_ty=ajax 方法: POST 参数:{ appId: "10001" expandParams: "" fp: "5525701123405161" //fingerprint platform: "web" timestamp: 1614687205087 version: "1.0" } 返回结果:{data: { result: { algo: "function test(token,fingerprint,timestamp,appId,algo){const random='jQ1SS0VI2Vuw';const str=`${token}${fingerprint}${timestamp}${appId}${random}`;return algo.SHA512(str)}" //加密函数 tk: "tk01w91541b51a8nWURUM3hiZk9HHRKep5j4FeOg/jHOQoGSDcsasdSOZ+83iz4uf/YBXHcK6xMIUqqv5/iJv6F0aooT5Nd3" //token } version: "1.0" message: "" status: 200 } } 将返回参数替换: const random : data.result.algo字符串中的const random='xxxxxx' const token : data.result.tk const fingerprint : 通过抓包APP获取 const hash1加密方法(例子:algo.SHA512、algo.MD5,主要看签名信息获取地址返回结果data.result.algo) */ function decrypt(time, stk, type, url) { stk = stk || (url ? getUrlQueryParams(url, '_stk') : '') if (stk) { const random = '1gy8nc5oDM+y'; const token = `tk01w9a771c1aa8nd1k2NUo4UmNaahBe0/qh61gMNV9222JdJwlR0wyO9gko9dFTogSpvPIpqxstZJ9tl8JM9ONKNJWk`; const fingerprint = 5525701217505161; const timestamp = new Date(time).Format("yyyyMMddhhmmssSSS"); const appId = 10001; const str = `${token}${fingerprint}${timestamp}${appId}${random}`; const hash1 = $.CryptoJS.HmacSHA512(str, token).toString($.CryptoJS.enc.Hex); let st = ''; stk.split(',').map((item, index) => { // st += `${item}:${item === '_time' ? time : item === 'zone' ? 'dream_factory' : item === 'type' ? type || '1' : ''}${index === stk.split(',').length -1 ? '' : '&'}`; st += `${item}:${getUrlQueryParams(url, item)}${index === stk.split(',').length -1 ? '' : '&'}`; }) const hash2 = $.CryptoJS.HmacSHA256(st, hash1).toString($.CryptoJS.enc.Hex); console.log(`st:${st}\n`) // console.log(`hash2:${JSON.stringify(["".concat(timestamp.toString()), "".concat(fingerprint.toString()), "".concat(appId.toString()), "".concat(token), "".concat(hash2)])}\n`) console.log(`h5st:${["".concat(timestamp.toString()), "".concat(fingerprint.toString()), "".concat(appId.toString()), "".concat(token), "".concat(hash2)].join(";")}\n`) return ["".concat(timestamp.toString()), "".concat(fingerprint.toString()), "".concat(appId.toString()), "".concat(token), "".concat(hash2)].join(";") } else { return '20210121201915905;8410347712257161;10001;tk01wa5bd1b5fa8nK2drQ3o3azhyhItRUb1DBNK57SQnGlXj9kmaV/iQlhKdXuz1RME5H/+NboJj8FAS9N+FcoAbf6cB;3c567a551a8e1c905a8d676d69e873c0bc7adbd8277957f90e95ab231e1800f2' } } 最后一步了,搜索${decrypt(关键字,大概有8处要修改,主要是团长这部分多,主要还是没有解耦: 参团部分(每一个api不一样,只要剥离出&h5st=${decrypt(xxxxx就行了,单独拼接): //可获取开团后的团ID,如果团ID为空并且surplusOpenTuanNum>0,则可继续开团 //如果团ID不为空,则查询QueryTuan() function QueryActiveConfig() { return new Promise((resolve) => { //option中的url拉出来替换如下 let url = `https://m.jingxi.com/dreamfactory/tuan/QueryActiveConfig?activeId=${escape(tuanActiveId)}&_time=${Date.now()}&_=${Date.now()}&sceneval=2&g_login_type=1&_ste=1` url += `&h5st=${decrypt(Date.now(), '', '', url)}` const options = { 'url': url, //改成变量 "headers": { ... taskurl和newtasksysUrl函数部分: function taskurl(functionId, body = '', stk) { let url = `${JD_API_HOST}/dreamfactory/${functionId}?zone=dream_factory&${body}&sceneval=2&g_login_type=1&_time=${Date.now()}&_=${Date.now()}&_ste=1` url += `&h5st=${decrypt(Date.now(), stk, '', url)}` if (stk) { url += `&_stk=${stk}`; } ... function newtasksysUrl(functionId, taskId, stk) { let url = `${JD_API_HOST}/newtasksys/newtasksys_front/${functionId}?source=dreamfactory&bizCode=dream_factory&sceneval=2&g_login_type=1&_time=${Date.now()}&_=${Date.now()}&_ste=1`; if (taskId) { url += `&taskId=${taskId}`; } if (stk) { url += `&_stk=${stk}`; } //传入url进行签名,加入位置不要错了,不然有些签名参数获取不到值 url += `&h5st=${decrypt(Date.now(), stk, '', url)}` ... 大功告成,发到手机上或者node跑一下试试: 结果非常完美。 docker处理 手机端好办,docker麻烦一点,放到远程或者本地都行,具体看说明jd_scripts docker。docker提供了一个环境变量CUSTOM_SHELL_FILE(你也可以用CUSTOM_LIST_FILE挂载本地定时任务列表,只是更新要手动,要自动还是需要脚本的)可以跑远程shell脚本,jd_scripts docker说明中还有示例,照葫芦画瓢即可。我在github上弄一份自用,你可以参考或者fork一份自己用,地址:jd_scripts-orzlee。只需替换decrypt函数部分常量就好了,shell脚本最好看看我写的注释。然后在环境变量中加入shell脚本地址CUSTOM_SHELL_FILE=https://raw.githubusercontent.com/xxx/xxx.sh即可。 如果用我仓库的远程脚本,务必docker配置环境变量RANDOM_DELAY_MAX=600, 600的值可以自己设置非零正整数,意思是所有脚本每天随机延迟0-600秒执行。 结语 经过不懈努力,终于还是折腾好了,这半个月都是手动点击脚本,人家升级都比我快,没办法手动哪里有脚本那么按时呢!混淆JS浪费不少时间,眼睛都能看瞎。
2021年03月03日
1,224 阅读
55 评论
4 点赞
2021-02-24
LXK0301京东签到脚本-自动提交互助码
前言 今天24号,刚好是LXK0301助力码清除日期,晚上给忘记了,到中午才发现今天互助码重置。 瞬间感觉错误一个亿,之前就想过要折腾个自动提交互助码的脚本,就是太懒了。今天亡羊补牢,折腾折腾。有兴趣可以用阅读我之前的文章QuantumultX-京东签到撸京东豆、openwrt-docker部署lxk0301京东自动签到脚本。 安装Telegram-Cli 此安装环境是VPS,openwrt上安装用docker,当然VPS也可以使用docker! 科学上网必备,没有一个良好的网络环境为前提都是白折腾!!! docker安装(推荐,省去一大堆麻烦事): 镜像地址:ugeek/telegram-cli 安装镜像: docker create --name telegram-cli -e TZ=Asia/Shanghai -v 挂载本地目录:/root/.telegram-cli ugeek/telegram-cli:amd64 启动docker: docker start telegram-cli 执行telegram-cli命令行交互(先执行一次登陆,输入telegram注册的手机号码,号码记得加区号。) docker exec -it telegram-cli telegram-cli -N -W 以下为编译安装步骤(docker或者编译二选一即可): 克隆telegram-cli: cd /root/work/telegram ### 或者你自己想要存放的目录 git clone --recursive https://github.com/vysheng/tg.git && cd tg 编译安装 ### ubuntu sudo apt-get update sudo apt-get -y install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev libevent-dev libjansson-dev libpython-dev make ./configure make 如果编译安装出现如下错误: 解决方法: apt-get install -y libgcrypt20-dev libssl-dev ./configure --disable-openssl --prefix=/usr CFLAGS="$CFLAGS -w" make 申请Telegram APP Key并且登陆telegram-cli 首先到telegram-apps里申请一个telegram App key(登陆时电话号码记得加国际区号)。 复制Public keys: 创建一个文件保存Public keys: nano /root/work/telegram/bot_key.pub ###鼠标右键粘贴 ctrl+o ##保存 按完记得敲车键 ctrl+x ##退出 登陆telegram-cil /root/work/telegram/tg/bin/telegram-cli -k /root/work/telegram/bot_key.pub ###输入账号绑定的手机号码,记得加区号 ###输入telegram App收到的验证码 IOS锁屏就会提示offline,打开手机telegram app就会提示online。 测试一下命令: telegram-cil频道名称如果有空格用下划线代替。 发送命令格式/root/work/telegram/tg/bin/telegram-cli -W -e "msg 频道名称 命令" ### 发送一条统计当前互助码池命令 /root/work/telegram/tg/bin/telegram-cli -W -e "msg Turing_Lab_Bot /count_activity_codes" 回显信息比较乱,自己看手机或PC telegram APP Turing_Lab_Bot机器人 消息就好了。 编写脚本 把互助码准备好,编写脚本: ### 创建一个文件,保存脚本 nano /root/work/telegram/submit_activity_codes.sh 2021-03-08 优化了定时任务脚本,速度更快,不会中断了,之前的脚本有问题,会经常中断(原因是因为脚本中执行发送消息命令太快-W参数加载消息会话列表没有完成就已经发出命令,导致命令出错!)。 复制以下内容,互助码自己替换,其他活动互助码自己添加(多个互助码用&拼接): #!/bin/bash telegramPath=TG Path #记得替换你telegram-cli目录/xxx/tg/bin ( sleep 5 ### @Turing_Lab_Bot ###京喜财富岛 echo "msg Turing_Lab_Bot /submit_activity_codes jxcfd 互助码" ###京东闪购盲盒 echo "msg Turing_Lab_Bot /submit_activity_codes sgmh 互助码" ###京东环球挑战赛 echo "msg Turing_Lab_Bot /submit_activity_codes jdglobal 互助码" ###惊喜工厂 echo "msg Turing_Lab_Bot /submit_activity_codes jxfactory 互助码" ###东东工厂 echo "msg Turing_Lab_Bot /submit_activity_codes ddfactory 互助码" ###东东萌宠 echo "msg Turing_Lab_Bot /submit_activity_codes pet 互助码" ##种豆得豆 echo "msg Turing_Lab_Bot /submit_activity_codes bean 互助码" ###东东农场 echo "msg Turing_Lab_Bot /submit_activity_codes farm 互助码" ### @Commit_Code_Bot ###JD签到领现金 提交助力码 echo "msg Commit_Code_Bot /jdcash 互助码" ###JD签到领现金 提交助力码 echo "msg Commit_Code_Bot /jdcrazyjoy 互助码" echo "safe_quit" ) | ${telegramPath}telegram-cli -W -D -D参数关闭了输出,调试的时候可以删除该参数(虽然没什么用,因为你命令发出去还没有等回显就已经结束命令了)。 docker 用户将最后一行脚本替换成) | docker exec -i telegram-cli telegram-cli -N -W,删除telegramPath=TG Path #记得替换你telegram-cli目录/xxx/tg/bin即可 保存脚本 ctrl+o ##保存 按完记得敲车键 ctrl+x ##退出 赋予脚本可执行权限 chmod +x /root/work/telegram/submit_activity_codes.sh 测试的时候记得注释大部分命令,留一到两个就行了,频繁提交小心被Bot Ban号。 bash /root/work/telegram/submit_activity_codes.sh 看看手机接收到的通知,一般接收到通知无非就是提交成功或助力池已满。 添加crontab定时任务 助力池每次清空日期为每月1,8,16,24号,延迟10分钟后执行: crontab -e 10 0 1,8,16,24 * * bash /root/work/telegram/submit_activity_codes.sh 结语 其他Bot签到什么的可以举一反三。 这下一劳永逸,省的忘记错过一个亿。最近京东活动也比较多,没有助力活动任务很难完成,助力才是京东活动的灵魂。
2021年02月24日
1,321 阅读
105 评论
2 点赞
2021-02-24
Emby公益服-上万部电影电视剧免费看
前言 过年这段时间比较无聊,找找电影看,之前从其他影视站找片源然后使用Airplay投放到AppleTV观看。说实话这些影视站片源广告多不说,质量不好,投影到电视上勉强能看,体验很差。 无意中Google到Emby终点站,这是个Telegram群组,家庭影院从这里开始。 加入Emby终点站 Emby终点站是目前片源最多、服务器最多的Emby公益服了。注册很严格,需要进行考核,考核随机40道题目,90分及格,考核失败必须72小时以后才能再次考试。而且及格后不一定立即能注册,需要等待开放注册。 2021-02-26(元宵节)会开放注册,开放时间随机 加入群组 群组链接:Emby终点站。 加入群组后一点要验证,验证失败两分钟秒后可以再次验证(最好等待验证通过后再进行考核,不然考核到一半Bot提示没有加入群组就很浪费时间了!)。 创建账号 考核Bot: EmbyPublicBot。 添加机器人后使用/create命令创建账号,如果没有考核会提示考核: 考核有点难度,一定要多看Emby终点站-Wiki,再结合Google,失败一次可是要72小时之后才能重新考核的。 毕竟是公益服,这样能拦下来大多数机器人注册,Emby终点站-Wiki多看几遍,写的很详细了,操作步骤都是图文结合。考核配合google,群组公告最好都看一下,管理很严格,容易Ban号。 如果你考试通过了,等待注册开放时间,再私聊EmbyPublicBot,使用/create命令创建账号: 按提示输入,创建成功后会返回服Emby务器地址和随机密码(要修改密码必须登陆到Emby客户端后修改,由于各个服务器之间不同步,所以每个服务器都需要单独修改密码)。 客户端 Emby终点站-Wiki已经包含很多平台客户端操作,我目前使用AppleTV,苹果设备Infuse6无疑是最好的了,就是价格感人。Emby官方客户端DTS音频是个问题。 infuse最好购买终身版Pro,可以先选年度订阅免费试用一个月后再做打算,以下是添加Emby服务器操作步骤: Infuse同步很坑爹,必须保持在视频库页面等待同步完成才行,中途退出APP或者浏览器他APP内页面、手机黑屏那么重来一次。像Emby终点站这样的大型公益服,片源很多最好找个好点的梯子,快的话半小时以内一个服务器的资源就同步完了。Emby官方客户端不存在同步问题。最坑爹的是手机同步完了到AppleTV又要同步一次!!! 添加的emby服务器越多,时间越长,好在第一次同步完后,之后更新会缩短不少时间,还是要看服务器新片更新量。 搜索功能一定要等待同步完成后才能用,否则是搜索不到emby服务器资源的 如果你添加多个Emby服务器,难免有重复的影片,那么影片也会重复显示的。这样有个好处,如果服务器1挂了或者网络不畅可以选第二个片源播放,麻烦的就是同步而已。 一直提示xxx目录错误多试几次,或者换其他emby服务器、梯子、取消合集,播放列表后面的勾,然后刷新视频库即可。一般来说尽量换emby服务器线路或者梯子。CF线路限制国家了,仅限 中国大陆及港澳台、日本、韩国、新加坡、澳大利亚、新西兰 的 IP 访问。( 使用 GCP 自建梯子的基本都是美国广播 IP,这些可能不能访问 )。就算其他公益服也差不多。 AppleTV Infuse 如果手机也使用Infuse,默认会通过iCloud同步所有emby服务器信息,只需点击APP右上角齿轮-媒体库中等待同步即可(千万别让AppleTV睡眠了,没事摸摸遥控器,或者干脆设置不自动睡眠)。 AppleTV infuse电影墙还是很不错的: 点击对应的服务器可以查看该服务器上的所有影片: 其他Emby公益服 卷毛鼠 Bot:卷毛鼠Bot 使用/register命令可以创建账户,这个公益服不用考试,直接创建账户即可。 普拉斯 通知频道: 普拉斯影业资源发布 这个公益服没有开放私人注册,作者之前尝试过,但是人数一多会对服务器造成很大压力放弃了。看频道公告使用公共账号。该公益服与很多机场合作,如果使用合作机场会有机场专线,可提供私人账号注册,但是机场服务器片源与公益服同步就不知道什么时候一次了,机场一般也不会保证,毕竟机场不是专门弄影片给用户看的。 AGA公益服(中国电信可直连观看) https://emby.plusmedia.site 端口: 443 CF公益服(仅限挂代理观看) https://emby-cf.plusmedia.site 端口: 443 备用服1: https://emby.xeton.dev 端口: 443 备用服2: https://jellyfin.xeton.dev 端口: 443 备用服3: https://movie.xeton.dev 端口: 443 备用服4: https://servers.xeton.dev 端口: 443 账号:普拉斯影业 密码:plusisbest 注: 使用方法见上图 (#备用服 仅限 Emby, Infuse 等客户端挂梯子登录观看) otakudrive 群组:OtakuDrive-EMBY https://emby.otakudrive.life (AGA) https://emby.neko.edu.rs (Direct HTTPS) http://emby.ok.edu.hk (Direct Non-HTTPS) 有NSFW内容 用户名: Guest 密碼: 1234 无NSFW内容 用户名: Guest2 密碼: 1234 客戶端: http(s)://(server address/伺服器链接) port: 443/80 公共账号唯一的缺点就是播放记录很乱,比如说你看了一半的电影,下次再看没法接着播放了(除非你记得播放时间,手动跳转),因为可能其他人也看了这部影片。播放记录也是乱七八糟的。 结语 公益服大多数片源质量很高,片源刮削也比较完整,虽然有些中文字幕没有刮削完整,凭借Infuse的刮削能力也可以很方便的获取字幕。要使用公益服还是自己准备好梯子,直连不能保证全天时间段都流畅播放。公益服承诺用不收费,都是大佬们自掏腰包。三个emby公益服加一次片源更加丰富了,最新电影肯定没有,因为公益服一般只折腾优质片源。 配合AppleTV或其他盒子,一个家庭影院就轻松完成了,完全省去NAS,自己折腾电源刮削都让人崩溃,耗时费力。
2021年02月24日
1,930 阅读
2 评论
0 点赞
2021-02-08
openwrt-docker部署lxk0301京东自动签到脚本
前言 最近弄了个软路由,J4105/8G/128G SSD,只是用来科学上网太浪费了,内存经常空闲7个多G,CPU 5%左右。 本来在手机上跑lxk0301大佬的京东签到脚本已经很爽了(有兴趣可以阅读我的文章-QuantumultX-京东签到撸京东豆),最近京东有个疯狂的JOY活动,自动看视频、领金币、合成JOY。脚本一旦启动不会停止,8s执行一次,手机上跑不太合适,可能会比较耗电。本想在服务器上弄个docker,想着软路由性能过剩还是折腾下软路由吧。 开撸 推荐科学上网后再折腾,虽然不是必要。 我是用的是eSir高大全,功能比较多,eSir youtube频道有固件讲解视频,包括一些使用教程等。 eSir高大全已经包含了DockerMan,如果没有可以去 DockerMan github看说明安装,当然也可以不使用DockerMan工具,看个人喜好。本片文章是基于DockerMan工具。 开始之前 默认eSir高大全的Overlay分区大小固定,如果硬盘较大其实很多空间都没有使用,可以看eSir说明以及教程OpenWrt扩容Overlay。 eSir推荐docker分区重新分配一个,这样在升级或者恢复出厂设置后不会丢失docker数据,所以在扩容Overlay分区的时候不要把硬盘全部用光,给docker分区多留点。这部分教程可以看eSir-玩转Docker系列视频,第一弹里面有讲到docker分区,视频中使用分区工具diskman,eSir高大全版本在openwrt管理页面 系统 目录下。 配置docker 2021-02-20 LXK0301 gitee仓库被大量外链访问封掉了,仓库访问已被禁止访问,返回403。目前已经套用CDN访问。 大佬telegram脚本更新通知频道JD_fruit Script。 以下是LXK0301大佬telegram bot最新消息: 云端使用仓库自带的docker。更新一下镜像后,然后可继续更新仓库最新脚本。 openwrt docker在 Docker-容器-点击容器名称-升级容器,旧的容器会在名称后面追加_old,删除带有_old的容器,启动新的就好了。 获取京东cookie方法,推荐使用扫码,可以保存cookies 90天。 环境变量说明总汇:jd_scripts docker 环境变量 在opt目录下创建一个目录,存放签到脚本目录,使用shell工具或者WinSCP操作 新建一个docker容器: 配置项 容器名称自定义 Docker 镜像 lxk0301/jd_scripts 始终拉取镜像 √ (每次启动、重启都会拉取最新镜像) 重启策略 Always 环境变量 JD_COOKIE必须,REPO_URL=https://gitee.com/lxk0301/jd_scripts.git 指定更新源,推荐gitee仓库,GitHub总是有人滥用GitHub Action导致作者仓库被封。gitee仓库不存在此问题,相对较稳定。我是用telegram推送签到信息(教程:Telegram通知BOT配置教程),其他环境变量去看jd_scripts docker 环境变量 挂载 具体看使用什么配置,jd_scripts docker 配置说明中举例了几种配置,一般默认挂载出日志文件就好了,当然也可以不挂载命令格式 第一步创建的目录:/scripts/logs,推荐使用绝对路径 点击提交后会回到第一步界面,勾选刚刚创建的容器,点击启动即可。 互助码 在你创建的并且挂载的日志目录下,jd_get_share_code.log、sharecode.log以及其他活动对应的日志中都包含该活动的互助码(如果活动可以互助的话),前两个日志文件会包含多个活动。如果没有想要的活动互助码只能在对应活动脚本日志中找,对应活动脚本(日志文件名与脚本名一致)可以查看脚本列表。 手机用户手动跑一遍脚本或者看看是否有脚本日志,一般会在日志或手动跑脚本的时候输出互助码 使用telegram提交互助码, 有两个BOT: @TuringLabbot @LvanLamCommitCodeBot 进入BOT点击消息输入框右边的斜杠按钮可以查看所有命令,使用/help查看说明,最好看一下,两个bot提交的互助码活动不一样,一个是长期活动,一个是临时活动。切勿频繁提交。BOT在1、8、16、24号0点会清空数据,0点后重新提交自己的互助码,作者服务器资源有限,互助码有上限(目前好像是5500个)。有兴趣可以折腾下:LXK0301京东签到脚本-自动提交互助码 docker容器相关操作命令 docker exec -it jd_scripts /bin/sh -c 'git -C /scripts pull && node /scripts/jd_bean_change.js' 手动拉取仓库最新脚本并且运行jd_bean_change.js脚本 docker exec -it jd_scripts /bin/sh -c 'env' 查看设置的环境变量 docker exec -it jd_scripts /bin/sh -c 'git pull' 手动更新jd_scripts仓库最新脚本 docker exec -it jd_scripts /bin/sh 仅进入容器命令(进入容器后也可以手动运行脚本: node /scripts/jd_bean_change.js) rm -rf logs/*.log 删除logs文件夹里面所有的日志文件(这行命令一般是在进入容器后执行) 结语 使用docker可以解放手机了,docker默认会开启jd_crazy_joy_coin.js脚本。这个docker不怎么耗资源,所以低配置软路由也没有问题,我同时跑了3个账号,除了内存上去了几百M,CPU还是老样子。脚本每天23:50会清空日志,每天会自动拉取最新脚本,所有挂上去后除了更新cookie基本上不用管。 diskman没法编辑环境变量,每次都要重建,在Docker-容器-点击你得容器名称-复制/编辑容器-可以复制一份容器配置文件,REPO_URL=https://xxxx 环境变量会丢失,估计是包含特殊符号,如果需要记得加上,补全信息:容器名称,始终拉取镜像,重启策略,修改cookie后删除原容器, 点击提交,操作麻烦了点,但比重新创建一个要简单。 有时候启动会无限重启,查看docker 容器日志会发现脚本没有执行完。 ... stderr: + expr 16 '%' 8 stderr: + remainder_h=0 可能是脚本BUG,当前时间小时数取余如果为0就会发生此问题,修改系统时间没有用,要修改容器时间才行,还是等待下一个小时在启动吧。
2021年02月08日
2,001 阅读
55 评论
0 点赞
2020-12-26
NeteaseCloudMusicApi +YesPlayMusic +UnblockNeteaseMusic搭建自己的音乐站(解锁网易云无版权音乐)
前言 最近逛论坛,看到一篇文章一台国内的1h1g1m小鸡可以做些什么?来看看我的吧(多图),其中有个项目吸引了我,网易云api及在线音乐播放器。顺腾摸瓜看教程。 可惜,文档比较少,前端知识也不够,折腾了我许久。别说前端技术目前来说也是相当强大的,长见识了。 必须要有国内服务器,不然UnblockNeteaseMusic没法用的,其他音乐平台都屏蔽了国外IP。 安装 一个个来,不然乱套了。 NeteaseCloudMusicApi 1.1 安装nodejs 这个比较简单,上命令:apt update && apt install -y git curl curl -sL https://deb.nodesource.com/setup_lts.x | bash - apt-get install -y nodejs 1.2 克隆NeteaseCloudMusicApi项目:git clone https://github.com/Binaryify/NeteaseCloudMusicApi.git cd NeteaseCloudMusicApi npm install 1.3 配置Nginx: 我使用的是Nginx反向代理:server { listen 80; server_name xxx.xxx.com; ### 记得替换 rewrite ^(.*) https://$server_name$1 permanent; } #跨域配置 map $http_origin $allow_origin { default ""; "~^(https?://[\w]+.domain.com)" $1; ##你的域名,记得替换,*.domain.com,这里可以添加多行域名 } server { listen 443 http2 ssl; ssl_certificate /xxx/xxx.cer; #证书 记得替换 ssl_certificate_key /xxx/xxx.key; #私钥 记得替换 ssl_prefer_server_ciphers on; ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; #屏蔽不安全的加密方式 server_name xxx.xxx.com; #域名, 记得替换成自己的 charset utf-8; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; proxy_hide_header Access-Control-Allow-Origin; proxy_hide_header Access-Control-Allow-Credentials; proxy_hide_header Access-Control-Allow-Methods; proxy_hide_header Access-Control-Allow-Headers; proxy_pass http://0.0.0.0:3000; ###API端口,修改了下面supervisorctl配置也要同步修改 # 跨域配置 add_header Access-Control-Allow-Origin $allow_origin always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,DELETE,PATCH' always; add_header 'Access-Control-Allow-Headers' 'Token,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,X_Requested_With,If-Modified-Since,Cache-Control,Content-Type' always; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } access_log off; #浏览日志,关了, 要开自己填写路径 error_log /var/log/nginx/xxx.xxx.xxx-error.log error; #错误日志路径 sendfile off; location ~ /\.ht { deny all; } } 1.4 需要添加一处代码,忽略ssl错误(大概122行左右,其实无所谓,因为是环境变量,但是要加在请求执行之前):nano NeteaseCloudMusicApi/util/request.js ... const settings = { method: method, url: url, headers: headers, data: queryString.stringify(data), httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }), } //添加下面这一行代码 process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; 1.5 配置supervisorctl守护进程: 安装:apt update && apt install -y supervisor 写配置 nano /etc/supervisor/conf.d/music-api.conf 端口3000,如果端口改了记得nginx配置文件也要改 [program:music-api] command=/bin/bash -c 'PORT=3000 HOST=127.0.0.1 /usr/bin/node /var/www/NeteaseCloudMusicApi/app.js' autostart=true autorestart=true user=root numprocs=1 更新配置文件,启动 sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start music-api:* 搞定,看看状态: $ supervisorctl status music-api:* music-api RUNNING pid 3312, uptime 0:57:01 1.6 如果不想用Nginx,那就记得服务器开放3000端口(或者你自己配置的端口, 还是建议使用Nginx)。 YesPlayMusic 以下步骤可以到本地操作,之后把编译的文件传到服务器就好了,当然服务器上操作也没问题。 2.1 安装yarn: curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list apt-get update && apt-get install -y yarn 2.2 安装YesPlayMusic: git clone https://github.com/qier222/YesPlayMusic.git cd YesPlayMusic yarn install cp .env.example .env 2.3 编辑.env环境变量: 用了Nginx填写域名,没有使用Nginx的填写http://服务器外网IP:3000(改了端口记得改) nano .env ... VUE_APP_NETEASE_API_URL=https://xxx.xxx.com VUE_APP_ELECTRON_API_URL=/api VUE_APP_ELECTRON_API_URL_DEV=https://xxx.xxx.com VUE_APP_ENABLE_SENTRY=false DEV_SERVER_PORT=20201 vue.config.js文件可以修改网页标题版权信息。 src/mian.js可以修改google analytics追踪代码ID。 src/store/actions.js 44行 document.title = ${track.name} · ${track.ar[0].name} - YesPlayMusic;这里YesPlayMusic是播放音乐的时候标题尾。 2.4 修改代码,为了后面使用UnblockNeteaseMusic: 文件路径 YesPlayMusic/src/store/actions.js。 ... // import { updateHttps } from "@/utils/common"; //注释掉 ... function getMP3(id) { return getMP3Api(id).then((data) => { // 未知情况下会没有返回数据导致报错,增加防范逻辑 if (data.data[0]) { // const url = updateHttps(data.data[0].url); //注释掉 const url = data.data[0].url; //添加一行 commitMP3(url); return url; } }); } ... } else { if (unblockSongUrl) { commitMP3(unblockSongUrl); } else { getMP3(track.id); } } } else { unblockSongUrl = getMP3(track.id); //添加一行 大改116行左右 commitMP3( unblockSongUrl || `https://music.163.com/song/media/outer/url?id=${track.id}` ); } }); }, 2.5 编译: yarn run build 2.6 配置Nginx: 此处需要新的域名,不能用NeteaseCloudMusicApi的域名 server { listen 80; server_name xxx.xxx.com; ### 记得替换 rewrite ^(.*) https://$server_name$1 permanent; ### 强制重定向到https } server { listen 443 http2 ssl; ssl_certificate /root/xxx.cer; ### 域名证书 ssl_certificate_key /root/xxx.key; ### 域名证书私钥 ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; #屏蔽不安全的加密方式 ssl_prefer_server_ciphers on; server_name xxx.xxx.com; root "/var/www/YesPlayMusic/dist"; #### 如果服务器上编译那就是这个目录,本地编译上传dist目录到服务器,然后填写dist目录地址 index index.html index.htm index.php; charset utf-8; location / { try_files $uri $uri/ =404; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log /var/log/nginx/xxx.xxx.com-error.log error; sendfile off; location ~ /\.ht { deny all; } } 2.7 Tips 其实这样就已经弄好了,只是我在折腾的时候发现了一个更又意思的东西,发现前端技术现在真心酷。 我是在windows上操作的,要先在windows安装Nodejs,yarn,这部分就直接去NodeJS、yarn官网下载吧! 我被electronjs坑惨了,根本不知道electronjs是跨平台桌面平台(相信很多前端都没有接触过这东西),使用electronjs可以编译出windows(MacOS, Linux)客户端,如果这样操作可以省去折腾UnblockNeteaseMusic,因为YesPlayMusic已经集成了。 起初只是看到YesPlayMusic有人提交PR,说是集成了UnblockNeteaseMusic,我就去看源码,发现 .env 中添加一个环境变量 IS_ELECTRON=true 就会开启UnblockNeteaseMusic,操作一番发现依赖electronjs通讯,window.require not a function 这错误让我在网上找了好久,其实是electronjs依赖nodejs,就算解决了 window.require not a function 问题,还是会接着来新问题。 后面发现electronjs不可能编译后通过浏览器使用的,这过程折腾了我一个晚上。 以下操作都是在本地windows系统操作的,可以按上文2-3部操作,NodeJS、yarn官网下载 开搞吧,先到.env中添加IS_ELECTRON=true。 安装electronjsnpm install -g electron 编译:"scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint", "electron:build": "vue-cli-service electron:build -mwl -p never", //编译macos, windows, linux三个平台 "electron:build-mac": "vue-cli-service electron:build -m -p never", //编译MacOS "electron:build-win": "vue-cli-service electron:build -w -p never", //编译windows "electron:build-linux": "vue-cli-service electron:build -l -p never", //编译linux "electron:serve": "vue-cli-service electron:serve", //运行服务,没什么用折腾我好久 "electron:buildicon": "electron-icon-builder --input=./build/icons/icon.png --output=build --flatten", "electron:publish": "vue-cli-service electron:build -mwl -p always", "postinstall": "electron-builder install-app-deps", "postuninstall": "electron-builder install-app-deps", "prettier": "npx prettier --write ./src ./script", "netease_api:run": "cd ./netease_api && npm run start", "netease_api:pull": "node script/pull.js", "netease_api:install": "cd ./netease_api && npm install", "netease_api:setup": "npm run netease_api:pull && npm run netease_api:install" }, 以上都是yarn run ...支持的命令,开始编译windows版本: yarn run electron:build-win 编译完了在YesPlayMusic\dist_electron目录下,进入目录,你会看到YesPlayMusic Steup.exe,这是安装程序,YesPlayMusic\dist_electron\win-unpacked里面有已解包程序YesPlayMusic.exe,点击就可以执行。 和网页版一样的效果,不得不说这界面做的真的好看。首页拉到底设置里面有深色模式。 点击右上角x并没有退出,最小化了,如果你再新开一个程序会提示你端口占用报错的。 UnblockNeteaseMusic 3.1 安装UnblockNeteaseMusic 其实也说不上安装,目前有四种方法: npx @nondanee/unblockneteasemusic docker run nondanee/unblockneteasemusic docker-compose up git clone https://github.com/nondanee/UnblockNeteaseMusic.git cd UnblockNeteaseMusic // node app.js //运行 不过暂时不用,下文配置supervisor守护进程 自己选吧,都可以用,前三种要自己生成163.com域名证书。 目前我使用的是替换host全局代理方法,其他方法实在懒得折腾了,真心累。 作者说替换host方法必须要开启80(443)端口,其实也不用(80端口占了就docker也能搞定),nginx反代就好了。 3.2 配置nginx: server{ listen 80; server_name music.163.com *.music.163.com; ##这里就别替换了 location / { proxy_set_header Host $http_host; proxy_pass http://127.0.0.1:3001; ##UnblockNeteaseMusic绑定端口 80 } } server { listen 443 ssl http2; server_name music.163.com *.music.163.com; ssl_certificate /var/www/UnblockNeteaseMusic/server.crt; ##不用换了 ssl_certificate_key /var/www/UnblockNeteaseMusic/server.key; ##不用换了 ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; location / { proxy_set_header Host $http_host; proxy_pass https://127.0.0.1:3002; ##UnblockNeteaseMusic绑定端口 443 } } 3.3 https反代歌曲URL域名: 此处需要新的域名,不能用NeteaseCloudMusicApi或YesPlayMusic的域名。 server { listen 443; server_name xxx.xxx.com; # 改为你自己的域名 ssl on; ssl_certificate /root/xxx.cer; ## 证书记得换 ssl_certificate_key /root/xxx.xxx.key; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; location / { proxy_pass http://localhost:3001; # 代理到 Unblock 服务地址 } } 3.4 修改hosts文件, 末尾添加,把域名劫持到本机,NeteaseCloudMusicApi请求API就会通过nginx到UnblockNeteaseMusic,让UnblockNeteaseMusic通过其他音乐平台获取相关资源: nano /etc/hosts ... ... 127.0.0.1 music.163.com 127.0.0.1 interface.music.163.com 127.0.0.1 music.126.net 127.0.0.1 interface3.music.163.com 3.5 添加supervisor守护进程: xxx.xxx.xxx用你的服务器ping music.163.com,然后替换掉。这里不使用-f参数指定域名会死循环的,直接爆出http 502错误 -e https://xxx.xxx.com 这个参数是指定歌曲URL输出域名,刚刚第3部配置的域名,网易的域名不会替换,只有网易没版权通过其他音乐平台获取的歌曲URL的才会替换。如果不替换的话其他平台大多只支持http协议,你的网站如果是https,chrome会强制https访问站点下所有资源(外链也不放过),这时候https其他音乐平台又不支持,嗝屁了。所以只能通过这种方式用服务器反向代理了。 nano /etc/supervisor/conf.d/music-unblock.conf [program:music-unblock] command=/usr/bin/node /var/www/UnblockNeteaseMusic/app.js -p 3001:3002 -s -f xxx.xxx.xxx -a 127.0.0.1 -e https://xxx.xxx.com autostart=true autorestart=true user=root numprocs=1 3.6 更新配置文件,启动 sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start music-unblock:* 看状态: $ supervisorctl status music-unblock:* music-unblock RUNNING pid 3373, uptime 2:39:00 搞定,nginx -t看看有错误没有,没错误nginx -s reload,然后打开网站看看。 结语 虽然碰到很多问题,但是确实有意思,感兴趣才有动力去研究。大大小小的坑都趟过去了,还有意外发现electronjs。 看Demo可以访问我刚刚搭建好的站点Music OrzLee,可能有点卡,毕竟UnblockNeteaseMusic要绕回国。然后套了CF,就随便看看吧,主要还是自己搭建个国内站点最好了。
2020年12月26日
408 阅读
3 评论
1 点赞
2020-12-24
Vue-videoJS播放m3u8视频
前言 找到一部分M3U8视频源,之前用H5 video 标签播放MP4视频,但是支持视频格式很少,索性换掉算了。 M3U8简单了解 引用维基百科: M3U8是Unicode版本的M3U,用UTF-8编码。"M3U"和"M3U8M3U8"文件都是苹果公司使用的HTTP Live Streaming格式的基础,这种格式可以在iPhone和Macbook等设备播放。 引用知乎: 上述文字定义来自于维基百科。可以看到,m3u8 文件其实是 HTTP Live Streaming(缩写为 HLS) 协议的部分内容,而 HLS 是一个由苹果公司提出的基于 HTTP 的流媒体网络传输协议。 HLS 的工作原理是把整个流分成一个个小的基于 HTTP 的文件来下载,每次只下载一些。当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。在开始一个流媒体会话时,客户端会下载一个包含元数据的 extended M3U (m3u8) playlist文件,用于寻找可用的媒体流。 HLS 只请求基本的 HTTP 报文,与实时传输协议(RTP)不同,HLS 可以穿过任何允许 HTTP 数据通过的防火墙或者代理服务器。它也很容易使用内容分发网络来传输媒体流。 简单理解,M3U8其实就是视频文件碎片索引URL(类似于播放列表),播放器会解析并且下载这些视频碎片,拼接成一整个视频。MP4格式对HTTP和Flash都比较友好,但是MP4文件头部结果比较复杂,播放过程对网络带宽要求较高,在网络复杂的场景用户体验较差。 Vue集成 集成之前大致了解了下,网上比较多的是vue-video-player和videojs,我选择了后者(之前video标签转过来还是不能跨度太大,免得拉跨)。 这东西让我折腾挺久的,只能怪自己懒,好好的文档不看,到处搜,结果搜到一堆复制粘贴的垃圾文章,也不知道什么年代的了,结果发布日期全是今年的。 官方文档相当简洁,其实非常简单,文档在此tutorial-vue,一目了然。 说说我的情况吧!,官方文档是在mounted方法中初始化播放器,但是我的视频流是动态加载的,这样直接加载会报错: CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED) No compatible source was found for this media 因为我的视频地址和视频类型都没有请求,只能在请求完成之后再初始化播放器。 播放器已经封装成组件了,看代码。 安装videojs: npm install --save video.js npm install --save @videojs/http-streaming //这个应该是不需要的,video.js在7.x就已经包含了,报错就还是加上吧,懒得试了 <template> <video ref="video" class="video-js" > <source :src="src" :type="video_type"> </video> </template> import Video from 'video.js' import '@videojs/http-streaming' import 'video.js/dist/video-js.css' //css要加载 export default { name: "playVideo", data: () => { return { player: null, } }, props: { width: { type: Number, default: 0, }, height: { type: Number, default: 0, }, src: { type:String, default: '', }, video_type: { type: String, default: 'video/mp4', } }, watch: { video_type(){ //监听props赋值,初始化播放器 this.initVideo(); } }, beforeDestroy() { //销毁不能少啊!!!!! if (this.player) { this.player.dispose() } }, methods: { pause() { this.$nextTick(function () { // DOM 现在更新了 // `this` 绑定到当前实例 this.$refs.video.pause(); }) }, initVideo() { //初始化视频方法 this.player = Video(this.$refs.video, { //确定播放器是否具有用户可以与之交互的控件。没有控件, //启动视频播放的唯一方法是使用autoplay属性或通过Player API。 controls: true, //自动播放属性,muted:静音播放 autoplay: "muted", //建议浏览器是否应在<video>加载元素后立即开始下载视频数据。 preload: "auto", //设置视频播放器的显示宽度(以像素为单位) width: this.width, //设置视频播放器的显示高度(以像素为单位) height: this.height, //网上很多没有用这个参数,默认获取<video><source src="" type=""/></video> //标签中的 source中的链接和类型,手动指定就可以避免动态获取视频信息的坑 sources: { src: this.src, //视频地址 type: this.video_type //视频类型 } }); } } } 结语 其实分分钟的是,搞了大半天。不过这个项目快一年没碰了,搞起来还有点懵逼。Graphql只用过一次,就是这项目上,Vue也好久没碰了,边熟悉边折腾,真是学无止尽啊。
2020年12月24日
275 阅读
0 评论
0 点赞
2020-12-22
QuantumultX-京东签到撸京东豆
前言 自从有了QuantumultX,各种签到脚本满天飞,调试、抓包都非常方便。京东签到脚本真的多,各种大大小小的签到、活动都做完,一天一百多个京东豆还是很容易的。 开撸 QuantumultX在1.0.17 (build 433) TF版加入了 task-gallery,而且正式版已经更新几个月了。 这东西就像是个脚本库,已经有大佬把脚本集合了,先放上来方便撸友: 2021-02-20 LXK0301 gitee仓库被大量外链访问封掉了,仓库访问已被禁止访问,返回403。目前已经套用CDN访问 大佬telegram脚本更新通知频道JD_fruit Script 以下是LXK0301大佬telegram bot最新消息,CDN节点已经屏蔽中国IP,需要梯子! 下面链接都是CDN,没流量了再说 BoxJs订阅地址:https://jdsharedresourcescdn.azureedge.net/jdresource/lxk0301.boxjs.json Surge的Task&Cookies脚本模块地址: https://jdsharedresourcescdn.azureedge.net/jdresource/lxk0301_Task.sgmodule.sgmodule Loon的Task&Cookies脚本订阅链接: https://jdsharedresourcescdn.azureedge.net/jdresource/lxk0301_LoonTask.conf 圈x: Task脚本订阅链接: https://jdsharedresourcescdn.azureedge.net/jdresource/lxk0301_gallery.json cookie脚本订阅链接: https://jdsharedresourcescdn.azureedge.net/jdresource/llxk0301_cookies.conf Peng-YM:https://gist.githubusercontent.com/Peng-YM/cc2cd6205b305d36544a44ec77129832/raw/gallery.json HotKids:https://raw.githubusercontent.com/HotKids/Rules/master/Quantumult/X/TaskGallery.json blackmatrix7:https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/script/gallery.json lxk0301 大佬:https://jdsharedresourcescdn.azureedge.net/jdresource/lxk0301_gallery.json 锄禾合集:https://dove.589669.xyz/task2qxgallery?sub=https://raw.githubusercontent.com/ChuheGit/1/main/Surge/Module/Task.sgmodule&img=1 打开QuantumultX,进入设置-构造请求(按红框标记点击): 点击+后输入上面大佬脚本地址,然后想要什么脚本就点击什么脚本,它会自动添加到定时任务中。 京东有些活动脚本不要随便修改执行时间,以免错失良机。 所有京东cookies通用,获取一次即可,保持一个月左右。 添加完脚本就要获取自己京东账号的cookies了,看大佬脚本描述: [rewrite_local] # 获取京东Cookie. # 注意此为远程路径, 低版本用户请自行调整为本地路径. https:\/\/api\.m\.jd\.com\/client\.action.*functionId=signBean url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/JD-DailyBonus/JD_DailyBonus.js [mitm] hostname = api.m.jd.com 在QuantumultX配置文件中编辑rewrite_local和mitm,加入上文代码。保存后用手机浏览器访问https://bean.m.jd.com,登录(安装京东APP后一键登录,方便快捷),手动签到一次,QuantumultX会提示获取cookies成功,这时大功告成。 有些活动到时间后一次几百京东豆,不亦乐乎。 上面大神们的脚本有些签到哦已经失效了,使用过程签到不成功之类的问题就不要疑惑了,直接放弃就好! 结语 大神太多,脚本都用不过来,各种签到脚本已经很全了,小众的签到只能自己抓包调试了。
2020年12月22日
1,792 阅读
0 评论
2 点赞
2020-12-22
Laravel-关系预加载数量限制
前言 最近开发一个项目,关于用户评论。评论可以被用户再次评论,当然只做了一级限制,没有做太多层级,可以回复某个评论中的特定用户(类似于@功能)。 在输出评论列表中,是应该输出部分评论的回复,但是看似简单,实际情况却相对复杂。 分析 在laravel中查询出两级并不难, 使用预加载可以轻松完成: class Comment extends Model { ... public function comments() { return $this->hasMany($this, 'comment_id'); } ... } Comment::with('comments')->simplePaginate() 当需要限制评论回复的数量时,首先想到的是如下方法: Comment::with( [ 'comments' => function (HasMany $query) { $query->take(5); }, ] )->simplePaginate() 但是返回的模型关系comments被限制小于等5条,并不是每条评论的回复,而是整个查询结果的评论回复。如果第一条评论回复有10条,那么会显示5条,之后其他评论的回复全部为空。 其中的Sql语句是这样: select * from `comments` where `comments`.`comment_id` in (1, 2, ...) limit 5 要实现每条评论显示N条回复并不难,只是回到了N + 1的问题, 查询出列表后再加载关系: $comments = Comment::simplePaginate(); $comments->each(function($comment) { $comment->load( [ 'comments' => function (HasMany $query) { $query->take(5); }, ] ); }); Sql: select * from `comments` where `comments`.`comment_id` in (1) limit 5 select * from `comments` where `comments`.`comment_id` in (2) limit 5 ... 这样确实可以解决问题,但是非常笨。 在laravel-framework的issue中找到了类似问题Eager-loading with a limit on collection...,其中有位开发者通过修改limit和take方法来实现预加载关系数量限制,但是提交PR被laravel作者拒绝,于是封装成扩展eloquent-eager-limit。 我安装后试了下,确实能达到效果,于是看了下源码。作者几乎把所有关系的limit和take方法全部重写,然后封装成Trait,模型中使用该Trait相当于重写了limit和take方法。使用方法和之前一样,但是要注意,一旦使用eloquent-eager-limit的Trait后,该模型就不再有之前关系limit或take的总限制效果了,相信laravel作者拒绝也是因为此原因。 来看看生成的语句: select laravel_table.*, @laravel_row := if(@laravel_partition = `comment_id`, @laravel_row + 1, 1) as laravel_row, @laravel_partition := `comment_id` from (select @laravel_row := 0, @laravel_partition := 0) as laravel_vars, (select * from `comments` where `comments`.`comment_id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) order by `comments`.`comment_id` asc) as laravel_table having laravel_row <= 10 order by laravel_row; 从Sql语句看来确实只用两次查询就可以获得结果,比之前load遍历加载方法更优。 来看看最终效果: { "data": [ { "id": 1, "post_id": 2, "comment_id": null, "contents": "contents...", "created_at": "2020-12-21 09:31:26", "comments": [ { "id": 24, "post_id": 2, "comment_id": 1, "contents": "contents....", "created_at": "2020-12-22 10:21:40", ... }, { "id": 18, "post_id": 2, "comment_id": 1, "contents": "contents....", "created_at": "2020-12-22 10:18:10", ... }, ... ], }, { "id": 7, "post_id": 2, "comment_id": null, "contents": "contents....", "created_at": "2020-12-22 09:38:07", "comments": [ { "id": 13, "post_id": 2, "comment_id": 7, "contents": "contents....", "created_at": "2020-12-22 10:11:02", }, { "id": 8, "post_id": 2, "comment_id": 7, "contents": "contents....", "created_at": "2020-12-22 09:59:43", } ... ] }, ... ], ... "status": "success", "code": 200 结语 其实也可以手动写Sql语句,缩成一条语句查询。但是太过于复杂的Sql并不易于维护,而且性能并不是一次复杂查询就一定比两次查询快。损失一点性能提高代码可维护性还是赚的。如果项目用户量较大,就要考虑缓存等其他技术优化了。
2020年12月22日
212 阅读
0 评论
0 点赞
2020-12-18
laradock-xdebug与php版本不兼容
前言 今天掉坑里了,为了添加grpc-php扩展,重新build php-fpm和workspace。过程相当顺利,而且启动docker都没问题,开发过程也没发现(api 调式和开发)。知道访问laravel-admin后台页面,访问半天打不开。HTTP 502错误。 摸索过程 出现502错误开始没在意,以为是早上composer update,太慢直接手动中断了,可能缓存什么的出问题了。 刚开始没在意,直到我尝试php artisan ide-helper:gen (ide-helper开发工具)时出错了 segmentation fault php artisan ide-helper:gen。 这下真有问题了。 尝试访问其他开发站点,登录页没有问题,laravel日志也没有。 查看docker日志 docker-compose logs php-fpm 出现大量日志 看到这行感觉莫名其妙: Illuminate\Contracts\Container\BindingResolutionException: Target [Closure] is not instantiable while building [Encore\Admin\Layout\Content]. in /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php on line。 不可能会出现这种错误啊,查看源码: namespace Encore\Admin\Layout; use ... class Content implements Renderable { ... /** * Content constructor. * * @param Closure|null $callback */ public function __construct(\Closure $callback = null) { if ($callback instanceof Closure) { $callback($this); } } } 构造函数有默认值,而且参数也是个闭包,不可能出现字符串Closure被容器实例化啊。简直一脸懵逼... 想断点调试代码,xdebug也失效了。开始用gdb调试过,发现大量xdebug关键字,想着八成与它脱不了干系。 去laradock看源码,对比本地php-fmp和workspace的Dockerfile文件,虽然没有新版本发布,但是这两文件确实有改动xdebug部分。 php-fpm ########################################################################### # xDebug: ########################################################################### ARG INSTALL_XDEBUG=false RUN if [ ${INSTALL_XDEBUG} = true ]; then \ # Install the xdebug extension if [ $(php -r "echo PHP_MAJOR_VERSION;") = "5" ]; then \ pecl install xdebug-2.5.5; \ else \ if [ $(php -r "echo PHP_MINOR_VERSION;") = "0" ]; then \ pecl install xdebug-2.9.0; \ else \ pecl install xdebug-2.9.8; \ fi \ fi && \ docker-php-ext-enable xdebug \ ;fi # Copy xdebug configuration for remote debugging COPY ./xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini RUN sed -i "s/xdebug.remote_autostart=0/xdebug.remote_autostart=1/" /usr/local/etc/php/conf.d/xdebug.ini && \ sed -i "s/xdebug.remote_enable=0/xdebug.remote_enable=1/" /usr/local/etc/php/conf.d/xdebug.ini && \ sed -i "s/xdebug.cli_color=0/xdebug.cli_color=1/" /usr/local/etc/php/conf.d/xdebug.ini workspace ########################################################################### # xDebug: ########################################################################### USER root ARG INSTALL_XDEBUG=false RUN if [ ${INSTALL_XDEBUG} = true ]; then \ # Install the xdebug extension if [ $(php -r "echo PHP_MAJOR_VERSION;") = "5" ]; then \ pecl install xdebug-2.5.5; \ else \ if [ $(php -r "echo PHP_MAJOR_VERSION;") = "7" ] && [ $(php -r "echo PHP_MINOR_VERSION;") = "0" ]; then \ pecl install xdebug-2.9.0; \ else \ if [ $(php -r "echo PHP_MAJOR_VERSION;") = "7" ] && [ $(php -r "echo PHP_MINOR_VERSION;") = "1" ]; then \ pecl install xdebug-2.9.8; \ else \ if [ $(php -r "echo PHP_MAJOR_VERSION;") = "7" ]; then \ pecl install xdebug-2.9.8; \ else \ #pecl install xdebug; \ echo "xDebug 3 required, not supported."; \ fi \ fi \ fi \ fi && \ echo "zend_extension=xdebug.so" >> /etc/php/${LARADOCK_PHP_VERSION}/cli/conf.d/20-xdebug.ini \ ;fi # ADD for REMOTE debugging COPY ./xdebug.ini /etc/php/${LARADOCK_PHP_VERSION}/cli/conf.d/xdebug.ini RUN sed -i "s/xdebug.remote_autostart=0/xdebug.remote_autostart=1/" /etc/php/${LARADOCK_PHP_VERSION}/cli/conf.d/xdebug.ini && \ sed -i "s/xdebug.remote_enable=0/xdebug.remote_enable=1/" /etc/php/${LARADOCK_PHP_VERSION}/cli/conf.d/xdebug.ini && \ sed -i "s/xdebug.cli_color=0/xdebug.cli_color=1/" /etc/php/${LARADOCK_PHP_VERSION}/cli/conf.d/xdebug.ini xdebug版本被限制在2.9.8,我去xdebug官网查看发现最新3.0.1,立马去workspace执行php -v: PHP 7.4.13 (cli) (built: Nov 28 2020 06:24:43) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies with Zend OPcache v7.4.13, Copyright (c), by Zend Technologies with Xdebug v3.0.1, Copyright (c) 2002-2020, by Derick Rethans 果然是最新版本,这是laradock问题,将php-fpm和workspace Dockerfile xdebug代码段替换再 build 就能解决了。 结语 xdebug 3.x估计是对应php8,目前开发环境使用PHP7,出现这种莫名其妙的错误真的很难调试。浪费大半天时间,重新build不知道多少遍,总之记住扩展不兼容也会出现各种莫名其妙问题。
2020年12月18日
218 阅读
0 评论
0 点赞
1
2
...
4