快速构建 nginx + v2ray + ws + tls 科学上网

前言

想想上一篇文章还是 2019年度总结,其实前几个月写了很多东西,都记在 Typecho 里,没写博客。为什么呢?因为知识点太过零散,自觉不方便写成文章,顶多记一记笔记这样子。

突然写这个是因为最近在 ruvds 租了一台机器用来挂给家里的 NAS 挂 bt 下载作代理用,因为移动不提供公网 ip,用 bt 下载速度太慢且几乎没有上传,我可不想一直做一个吸血鬼。

ruvds:一个月 60 卢布,6块钱左右,可以用万事达借记卡支付,很划算。

为什么使用 WebSocket + TLS

因为无论是 Vmess 亦或者 SS 协议,只要流量过大都会导致断流和封端口,遂只能另寻它路。Trojan 和 v2ray + ws 的伪装流量可以解决上述问题,这也就是这篇文章的由来。

准备工作

  • 一台墙外的机器
  • OS选择:Ubuntu / Debian / Centos
  • 一个域名

快速构建

开始

下列命令均在 root 用户下进行(su root 或者 sudo -i)且使用 Debian 9 系统,Centos 需要一些改变

  • nginx:提供网站服务
  • v2ray:提供 socket 代理服务
  • Certbot:自动配置证书,开启 tls

安装必要程序

安装 nginx:apt update && apt install -y nginx
安装 v2ray:wget https://install.direct/go.sh && bash go.sh

安装 Certbot:
OS 不同,方法不同,参考 https://certbot.eff.org/

配置 Nginx

先将域名解析到 vps 上,然后 cd 到 /etc/nginx/conf.d,添加文件 v2ray.conf,填入以下内容,文中 example.com 修改为你解析到 vps 的域名

server {
	server_name example.com;
	root /var/www/ray;
	location /ray { # 与 V2Ray 配置中的 path 保持一致
    if ($http_upgrade != "websocket") { # WebSocket协商失败时返回404
        return 404;
    }
    proxy_redirect off;
    proxy_pass http://127.0.0.1:10086; # 假设WebSocket监听在环回地址的10000端口上
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    # Show real IP in v2ray access.log
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }	
}

填写完成后使用 nginx -t 测试语法是否正确,然后 systemctl restart nginx 重启服务,创建 /var/www/ray 这个目录,建一个 index.html 文件,内容随意

配置 Certbot

输入 certbot ,选择你的域名

root@ip-172-26-6-133:/etc/nginx/conf.d# certbot
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: ray.yukino.ch
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for ray.yukino.ch
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/conf.d/v2ray.conf

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Redirecting all traffic on port 80 to ssl in /etc/nginx/conf.d/v2ray.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://ray.yukino.ch

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=ray.yukino.ch
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/ray.yukino.ch/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/ray.yukino.ch/privkey.pem
   Your cert will expire on 2020-09-17. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

至此,直接在浏览器访问你的域名应该可以看到 index.html 文件,如果没有,检查一下 80 / 443 端口是否打开了(telnet exmple.com 80)

配置 V2ray

修改 /etc/v2ray/config.json 文件, id 改为 你 生成 的 UUID

{
    "inbounds": [
        {
            "port": 10086,
            "listen": "127.0.0.1",
            "protocol": "vmess",
            "settings": {
                "clients": [
                    {
                        "id": "xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
                        "alterId": 64
                    }
                ]
            },
            "streamSettings": {
                "network": "ws",
                "wsSettings": {
                    "path": "/ray"
                }
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "freedom",
            "settings": {}
        }
    ]
}

然后 systemctl restart v2ray 重启 v2ray,至此所有内容配置完毕

客户端连接

客户端连接的时候设置 path 为 ray,开启底层传输安全(tls),地址即为你的域名,用户 id 即为你的 uuid

我的 2019

写在前面

中学时期已过,生活不再是反反复复的学习,年度总结也有得写了。

2019 是我诞生的第十八年,回想起来,这一年发生了很多意料之外的事情:精神出问题、身体坏掉、志愿被调剂。当然,也有按照普通人生计划走的事情:高考、大学入学、成年。另外,我在许多方向做了些许尝试,发现了自己喜欢的很多东西。

在生活上

精神出问题,人也随之坏掉。由于某个无法改变的现实原因,以及长年以来的强迫思维,高三开学不久后负面情绪达到阈值,顷刻间爆发。在一段时间内被 OCD 取代了真正的内心,抑郁情绪也在心里反复翻涌。生与死的界限变得模糊,变得经常考虑死亡的可行性,然后再被理性一一否决。舍曲林吃和没吃一个样,甚至会让我长期精神紧绷,仅是来自外界的细微干扰也时常会吓我一跳。
心里出问题,这个事实被理性了解得一清二楚。坐以待毙不是我的风格,要潇洒,要始终浪漫。以自救为动机的我推开了变态(abnormal)心理学的大门。这个领域,真正地让我触碰到了人类最为脆弱的一面。同情自己,也同情那些更严重的精神症患者,一边面对恶魔,一边努力地活着,实属不易。查阅了很多资料后,对所谓顺其自然,为所当为。有了自己的理解。
何为自然?窗外的冷风、天空的太阳就是自然,婴儿诞生、树木凋零也是自然。而 OCD 让我违背自己的自然,后果便是精神崩溃。从某刻起,我决定遵从自然,接近自然。自然中的自己无限接近于洞穴外的美景,而被困在 OCD 中的自己只能看着墙上的影子生活。因此,我将自然视作自己的主,我成为了一个泛神论者。
我所做的这一切,只是为了拯救自己,但却恰好叩开了哲学领域的大门。原来我一直思索的问题已经有前人思索,这让我十分欣喜,原来高中课本上枯燥无味的“哲学”并不是哲学,真正的哲学是如此有趣(同时也更加无用),我的理想就是做个无用的 thinker。
由于长期地精神压抑,病了一场,在医院躺了半个月。十分感谢父亲母亲,在我最困难的时候给予我关怀,父母是真正能够无所保留为我付出一切的人。这场病让我明白了生命的脆弱,明白了父母的无私,明白了精神决定机械的肉体。以后精神状态不能过于压抑,压抑会毁掉本就是一具机械的身体。
六月七八号,我经历了高考,为中学时代画上句号。值得一提的是,监考老师是两年的班主任和高一地理老师,原来如此,结束更意味着新的开始。高考不过如此,几个小时,几张卷子,将我送往不同的地方。
志愿填报的时候,每个志愿都填了 CS、EE,最后却吃了一波调剂,让我不得不感叹生命之轻。没事,问题不大,条条大陆通 CS,准备考研了。就算我不是科班生,不也呆在图书馆嫖着书看得津津有味,正如现在手边放着一本《Linux 基础及应用教程》,我拿专业课门门都考60分,有何问题呢?
关于感情问题……这里似乎没什么好写的。

我看的书

反而上了大学以后却看得少了,值得反省。

  • 《天黑以后》
  • 《海边的卡夫卡》
  • 《围城》
  • 《我心中尚未崩坏的部分》
  • 《月亮与六便士》
  • 芥川龙之介的一些短篇
  • 《这才是心理学》
  • 《变态心理学》
  • 《改变心理学的五十个实验》
  • 《苏菲的世界》

田村为理想出走,最终却回到现实,脱离现实的理想原来死气沉沉。
许多人最后都活成了方鸿渐的样子,一如歌词“得不到的永远在骚动,被偏爱的却有恃无恐”。
即使后悔出生到这个世界,却仍要继续活下去,这也是一个觉悟吧。
火光映红了半片天空,理想在火中燃烧,最终归于天际,留下一堆漆黑的粉末嘲笑无药可救的现实。有的人出生在异地,究其一生都在追求回到理想中的故乡。

在我的领域

至今仍在尝试不同的方向,还是很菜很菜的。
目前的技术栈停留在 C# 做桌面程序,PHP 和传统的前端搞 web。问题是两者都还不够深入,都还在处于半斤八两的状态,这样真的不行,欠缺深入,欠缺打磨,一定要摸到底,理解透彻才行。下一年要在这两个方向分别作出令我满意的作品。

人不可能有全才,找到一个方向钻研下去才会有结果。下一年要确定具体的发展方向,只不过喜欢的太多了,似乎一个方向并不足以消磨掉满溢的热情。

走好,2019。

你好,2020。

OLAINDEX-Magic:OLAINDEX的魔改版本,支持多账户挂载

这是什么?

一款 OneDrive 目录文件索引应用,基于优雅的 PHP 框架 Laravel5.8 搭建,并通过 Microsoft Graph 接口获取数据展示,支持多类型帐号登录,多种主题显示,简单而强大。

前言

读了代码,原作者很厉害,MS Graph接口封装得很优雅,前端也写得挺好。相比之下的我自惭形秽,想想二开只不过是把大佬的代码弄乱而已。

OLAINDEX许久没更新了,我决定尝试为它添加新功能,并长期维护,谨以此学习Laravel框架。

演示站点https://magic.yukino.co/
原项目地址:https://github.com/WangNingkai/OLAINDEX
魔改项目地址https://github.com/YukiCoco/OLAINDEX-Magic

魔改内容

  • 多Onedrive账户支持:
    • 可同时挂载多个Onedrive网盘
    • 图床可选择上传到不同的盘区
    • 多网盘命令支持
  • 一些小修复:
    • 一键获取下载链接
    • 图床复制链接
    • Ajax删除文件
    • ……

如何 绑定&使用多账户

登录Azure:https://portal.azure.com/https://portal.azure.cn/ (世纪互联)
点击 Azure Active Directory
点击 应用注册
点击 新注册 名字任意取,账户类型如图,重定向URL填你页面所显示的redirect_uri

接下来配置API权限,操作看gif:演示图片链接

接下来点击 概述 复制 应用程序(客户端) ID(client_id
点击 证书和密码 添加新客户端密码并复制(client_secret

在绑定页面填入client_id client_secret 选择好账户类型即可绑定。

绑定多账户见:

冷 夜

陌生的城市凄冷的夜晚,我对未来毫无概念。如果明天不会来该多好,如果我不曾存在过该多好。

我能看到那个地方,那里夜空星辰遍布,月亮占满了半片天空。那里的海面被抹上天空的色彩,男孩女孩牵手坐在沙滩边的断木上。那里一片晴空,屋檐下的阴影是温暖的黑暗。

那里不用考虑时间的存在,片刻便是永恒。

如果死亡可以拯救别人,我会怎么选择

看完《青春猪头少年不会梦到怀梦美少女》,本来打算娱乐看看的,但剧情却出乎意料有些深度。

剧中抛出一个问题:已知我的死亡可以使翔子获得生命,是避开还是继续走向这条线?

我真的真的不想看麻衣哭泣,也不想听理央颤抖的声音。我深知死亡意味着什么,但我还是会选择自己死去,对不起。

即使是这样懦弱的我,也有勇气直视死亡。
自己与别人的生命,我会选择别人。
潜意识就会做出这样的选择,我无法改变。
对不起,喜欢我的人们。

死不是生的对立面,而是作为生的一部分永存。

《挪》村上春树

可能也有自私的成分吧,因为死亡真的能一了百了。

服务器搭建离线下载的尝试与实现方式

前言

经常需要从外网下载很多东西,但由于国内「墙」的存在使得下载速度慢得一踏糊涂,甚至无法访问。手头有一台cloudclone的服务器(就是现在跑网页的),以服务器作为中转下载,然后再取回,这样可以达到不错的下载速度(使用idm等多线程下载器

过程

首先尝试搭建了Cloudreve,号称基于aria2的离线下载,支持对接一些网盘储存。安装过程蛮顺利,但使用中发现了一些问题:

  • 界面逻辑应该改善:可以说是金絮其外,败絮其中。Material-UI挺漂亮,但交互做得不是很好,比如在首界面点击左边的音乐/视频后直接进入搜索模式获取对应格式的内容,然而界面上却没有提供返回键。
  • 基于aria2的离线下载存在问题:需要先下载在一个临时文件夹里再由PHP复制取回,原文件由于权限不能够被删除,这就导致了下载一个文件需要用双倍的空间。不能删除因为在宝塔面板里php和aria2的执行用户是不同的。

之后尝试了oneIndex以及olaIndex,,这两个都可以挂载onedrive使之以直链的形式被导出。但前者在onedrive高峰期会因为API问题无法访问,后者测试的时候死活绑定不了网盘账号。
类似的程序还有PyOne及CuteOne,由于搭建需要Nginx,所以没再测试。

实现方式

Aria2和AriaNG下载文件,以脚本上传至Onedrive,再由rclone挂载Onedrive到h5ai的目录实现网页端读取功能,文件管理使用kodexplorer。
在选择文件管理器时也遇到了一些坑,filerun和nextcloud试了一圈,最后选择了kodexplorer。
经测试一部分视频文件由于解码问题无法在h5ai播放,又挂了一个FTP方便iPad看视频。

搭建方式参考如下,不再赘述。
https://www.moerats.com/archives/700/
https://www.moerats.com/archives/697/
https://www.moerats.com/archives/491/
https://www.moerats.com/archives/870/
https://larsjung.de/h5ai/
https://kodcloud.com/

其中需要做出一些修正:

想要挂载多个盘的话,Rclone服务需要做一些修改

#以下是一整条命令,先修改DriveName:Folder和LocalFolder的值,再一起复制到SSH客户端运行
#rclone.service可改为 任意名.service 这样可以挂载多个网盘
cat > /etc/systemd/system/rclone.service <<EOF
[Unit]
Description=Rclone
AssertPathIsDirectory=LocalFolder
After=network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/rclone mount DriveName:Folder LocalFolder \
 --umask 0000 \
 --default-permissions \
 --allow-non-empty \
 --allow-other \
 --buffer-size 32M \
 --dir-cache-time 12h \
 --vfs-read-chunk-size 64M \
 --vfs-read-chunk-size-limit 1G
ExecStop=/bin/fusermount -u LocalFolder
Restart=on-abort
User=root

[Install]
WantedBy=default.target
EOF
#rclone改为你修改的服务名
systemctl start rclone #启动服务
systemctl enable rclone #开机自启

上传脚本需要做一些改变,重载onedrive挂载盘:

#在上传脚本末尾添加,用来上传完毕后重启rclone服务
#我这里的服务名字为上面自己改的rcloneOD.service
systemctl restart rcloneOD;

对Aria配置做一些改变,更多参数参考官方doc:

# 当种子的分享率达到这个数时, 自动停止做种, 0为一直做种, 默认:1.0 (分享率为共享提供几份文件
seed-ratio=1.0
# 最大做种时间 单位分钟
seed-time=150
#以上两个参数为逻辑或

完毕

离线下载内容会自动上传至onedrive并删除本地文件,通过h5ai可导出onedrive直链下载链接,视频文件可直接通过网页流媒或以FTP的方式观看。

我的h5ai分享站:
http://file.yukino.co/

十八岁

二零零一年到二零一九年,十八个年头从指间溜走。我也从当初那个天真浪漫的小孩子变成了今天的这幅模样。(自认为现在也很浪漫)其实我早早地就有了成年人的偏见,有了成年人「污秽」的东西,不想狡辩,我就这样大大方方地承认吧。

到现在为止,理想主义始终被我放在首位,我努力让自己活得更加自由。尽管有那么些时候会碰壁,但我抹抹鼻子,相信换个方向也能抵达终点。十八岁,可以很清晰地察觉到「自己」的时间在减少,甚至察觉最后「自己」也会消失殆尽,但没关系。消失是存在的一部分,如同村上所说“死亡不是生的对立面”。以往的这些年,我如田村卡夫卡,从现实中莫名其妙地消失去,遁入理想世界中。可真正地到了那里才发现,所谓的理想仍然是人类的小玩意,它又会重复,最后成我们现在的文明。而我现在处于一个回归社会的过程,带着理想主义返回社会,接受现实,并希望能改变现实。姑且让我把那句话改一改:愿我出走半生,归来仍是少年。

「0」在当下,「1」在未来,现在由我自己来定义。想做什么去做,想学什么去学,反之亦然,这就是我所理解的自由。

以前的我经常受人帮助,有了他们才有我的现在,才能有这个十八岁,请让我继续厚着脸皮说:以后的日子也请多多关照。越长大越有责任,不仅是对家人朋友,也对陌生人,对这个社会,甚至对国家。现在不是八九十年代,我不必再以“为中华崛起而读书”来贴上红旗标签,但意义犹在。

以此篇纪念我此生唯一的十八岁,至此搁笔。

改变不了的改变

对未来期待着,迷茫着,恐惧着。

我渴求着未来会有所不同,却不知自己要有什么不同,恐惧着这样的生活:毕业工作结婚过完这一生。

如果一切努力都是以此结尾,那努力有何意义?

为何要活着?目的是为何?我为何存在于此?我是个什么东西? 我面前的所有真的有意义吗?

看着谈笑风声同学,看着地铁站来来往往的人流,看着校园里手牵手的情侣……
怎么也想不出生命的意义在于何处。

高中老师、军训教官,说他们已经固定了人生,已无法再有改变,说我们应该有所不同。

但是,我们应该有什么不同呢?毕业工作后,生活也随之固定了吧,也逃不出和他们的套路吧?

说什么改变,所有都已被决定,我们只不过是走过程罢了。

C# 事件(Event) 学习笔记

为了实现WPF界面下的断点续传等下载功能,从Github上找到这个项目: https://github.com/markodt/SGet
里面的下载类使用了一些事件
我以此来学习事件的用法

首先C#中没有事件这个类型,事件是一个特殊的委托。

下面是一个简单事件声明(没有使用参数

//声明下载完成事件
public event EventHandler DownloadCompleted;

//定义事件触发函数
protected virtual void RaiseDownloadCompleted()
{
    if (DownloadCompleted != null)
    {
       //注意这里的EventArgs.Empty
       DownloadCompleted(this, EventArgs.Empty);
    }
}

//在某处使用触发函数,触发事件
public void Start(){
this.RaiseDownloadCompleted();
}

//其他地方有需要时就调用事件
WebDownloadClient download = new WebDownloadClient(url);
download.DownloadCompleted += download.DownloadCompletedHandler;

然而上述的做法并不安全,参考:

//3.定义触发事件的方法
protected virtual void OnNewMail(NewMailEventArgs e)
{
    /* 第1种做法            
     if(this.NewMail != null)
     {
        this.NewMail(this,e);
     }            
     */
     
    /* 第二种做法
    EventHandler<NewMailEventArgs> temp = this.NewMail;
    if (temp != null)
    {
        temp(this, e);
    }
    */
 
    //第三种做法
    EventHandler<NewMailEventArgs> temp = Interlocked.CompareExchange(ref this.NewMail, null, null);
    if (temp != null)
    {
        temp(this, e);
    }
}

第一种做法是很常见的做法,判断不为空,然后就触发。CLR里提到这是线程不安全的做法,因为单我们判断不为空后,准备执行时,另一个线程将从委托链将委托移除,此时变成了空,引发NullReferenceException异常。
第二、三种做法都是线程安全的,因为它通过一个临时委托变量(委托链保存了所有委托),通过上一篇对委托链的了解,我们知道对委托链进行Combine/Remove实际都会创建一个新的数组对象,此时对temp没有影响。但实际上事件主要在单线程的环境下使用,所以一般也不会出现这种问题。

来自 https://www.cnblogs.com/ldyblogs/p/event.html