大一刚开始时,因为一点小的契机,开始做一个小的面向校园的项目

在之后过去的三年中,从无到有,一个人把整个开发流程全都体验了下来

分析需求-设计-开发-测试-部署-维护-客服 如此往复....
最要命的是,为了让自己优雅起来,多个平台多个语言的 native 开发,多份代码令人沉醉

全都自己包揽下来,显然是没有沟通成本的,自己决定所有的事情,令人开心

然而纵观整个流程,大量繁琐蛋疼的工作逐渐的让我在意起来:
故障发生后用户反馈才知道-需要监控
Server新代码手动上线十分麻烦,客户端发新版真要命-需要自动化部署
买了个新vps配置半天真要命-需要自动化运维

于是想办法:
运维怎么办?Ansible吧,能实现一点简单的normalize就可以了
监控和部署怎么办?Zabbix+Jenkins? 小项目不想上那么大的东西...
于是代码里TopExceptionHandler一把梭,和Telegram Bot对接实时通知,简陋的监控完成
然后用git push hook做了个简单的服务端部署自动化,给客户端自动更新的接口做了个简单的管理页面。

然而感觉git hook的配置太麻烦,于是又写了个脚本自动配置 hook。
自动配置hook的脚本:https://gist.github.com/StoneMoe/8c897122a32776c1ee0252f605b01e2c

于是简陋又简单的自动化系统搭起来了)

而最近写bot的时候,直接用了Sublime SFTP 的 Mapping 功能,更加的一把梭了)

之前写了几篇关于找工作的没干货的杂文,还是合并一下吧。
(弱鸡是没有生存空间的233,面试的时候尽管遇到的面试官都相当nice,可是能感受到部分面试官透露出来的丝许鄙视的感觉...)
(谢谢过程中帮我的朋友们....感动哭了....各种内推,帮忙改简历,甚至在rr家住了一晚什么的....)

腾讯
=
还是懂的太少,之前一直想补基础知识,然而一直没有找时间开始啃,所以有没有非科班学生学习计网组成等基础学科的好去处呢,难道真的只能自学吗
11月2日的我:是的只能自学你赶快多看点书别整天感叹了233
人生中第一次面试,大脑一片空白,全程盯着窗外大脑疯狂运转有什么说什么,最后说出来的全是废话。
Sad.

面试
-
"为什么学的是游戏和艺术方向的,不去应聘相对应的岗位"
"我...我...还是有做技术的心..."(我tm在说什么)
然后围绕简历让我推销一下自己(估计是看我简历写的比较杂)
从中聊了一些具体项目和事件的细节,遇到的困难
写没写过爬虫,怎么实现的
逆过的东西讲一讲经历
问了问自己以后想要做的方向(感觉除了能力,也挺看和缺人的职位对不对口)

然后在酒店咸鱼了两天思考人生,等到了没有合适岗位的通知;w;

在线笔试
-
比较疑惑的有一个问题

使用 GRE 洗 DDoS 的缺点是______

 1. 把以前看大佬聊天时提到的GRE BGP等协议又复习了一遍,不过没找到什么相关的通用技术描述。
    最后查到了一个流量清洗服务商(psychz)提供的技术细节:https://www.psychz.net/client/question/en/ddos-protection-using-bgpgre.html
 2. 自己理解了一下,大概指的是受到攻击之后先 BGP 把 route 拉到清洗服务商的 AS 上,然后等洗完之后 GRE Tunnel 传回来。
    和大佬讨论了一下,最终观点也差不多是这样。
 3. 缺点大概是延迟会增大,大概和GRE也没有什么关系,流量被拉走清洗再回来肯定会延迟增大的啦...
 4. BGP 似乎是可以声明 /32 的,不过上面那个技术细节链接里面描述的需要声明 /24 应该是他们的服务不太行....(补充:公网声明应该是要求/24的,要不table太大了,现有设备都受不了,至于有些服务商支持小于/24应该是他们把流量导进来然后自己再做针对/32的route)

再引用一下讨论过程吧:

T:

当IDS检测到攻击时,通过BGP发布一条主机明细32位的主机路由 并打no—export和100:101团体属性
让相应的入口路由器下一跳指定为tunnel的私有地址 发布给SP其他AS入口路由器使相应主机的流量通过GRE隧道传送到清洗设备
然后...balabala
大概好像差不多就酱。。。。好早以前好像看人讲过

Z:

buyvm 的 wiki 有篇文章,就是教你去买 ovh 的 vps...然后起个 gre,直接全端口转发 ovh ip 所有流量到自己的 buyvm 机器....
然后日常使用 ovh 的 ip,这个 buyvm 太鸡贼了。

M:

buyvm 自己的高防 IP 是广播到 voxility 清洗的
psychz 那个方案是自己的 IP 平时按正常的线路广播,被攻击的时候 BGP 把流量引到他们的清洗上,他们会通过 GRE 把清洗后的流量回源。
不过 psychz 这个一个 IP 被打就得切整个 /24...

T:

一个C段都被拉去洗了。。。

M:

BGP 广播需要这样

T:

BGP可以播/32的吧0.0

M:

他们的清洗不行呗
只接受 /24

T:

华为的sinkhole也是类似的技术,把GRE和BGP结合起来做流量清洗

看了一下 Sinkhole 白皮书,技术细节那一块确实说到了 BGP 和以 GRE 为例的 Tunnel 技术结合起来做流量清洗和回源

B站
=
面完之后感觉自己就是个垃圾
有一段时间了所以只记得这么一点了

面试
-
围绕简历问的比较少,能够明显的感觉到是直接针对业务问的
先让介绍一下自己
然后问会不会lua
抗撸羊毛怎么做
几种开发模式了不了解,有什么区别
Android 了不了解(会写一点不代表了解Android,于是干脆说不了解了)
RSA 使用不当导致的弱点

  1. RSA 使用过程中使用不当导致出现漏洞的一些情况
    找了一篇文章

原文:http://www.shiyanbar.com/questions/989
备份:https://www.evernote.com/shard/s438/sh/59323698-097b-4e9b-9404-4015949863ec/0190984b755a032d76b8bf0a69e8bc89

  1. MVC, MVP, MVVM 的区别
    面的时候一脸懵逼不知所措,好像没有听过 MVP

最后只能说是自己不懂,跳过了这个问题
事后一查才想起来这玩意我只在几年前看设计模式相关的文章才见过...
至于有什么区别,现在再一想,先总结一下自己的理解,要是有问题欢迎指出:D

1.他们都是将 Model,View,Logic 这三大块抽象出来
2.在不同的业务场景下,这几个部分有的会写的比较厚有的会写的比较薄...
3.主要的区别大概在于这三大块的调用链和耦合程度
4.MVVM 独有的方便的双向绑定特性XD
  1. 怎么抗撸羊毛
    脑袋一片空白,没有这方面经验随便答了几点,现在重新想一想:

1.用户真实性评分,参考多个方面的指标:注册时间,视频观看量,评论数量,虚拟道具使用记录,实名认证,历史登陆地点,历史登陆次数,说白了就是根据以前的账户活动来判断,这么来看,用户等级也是真实性评分的一种体现形式
2.单用户/手机号/实名验证 做对应关系(对于羊毛团队来说成本还是比较低,但是有必要,并且用途不局限于此)
3.活动奖励控制成本,撸羊毛无法完全挡住,只能努力的提高对方成本让对方利润降低
4.对已经筛选出来的手机号做猫池黑名单
5.线下类奖励做消费时的实名验证
6.如果羊毛需要转出给普通用户才能获利,可以钓鱼执法(
7.特征分析,比如用户名特征,异常客户端行为,用户资料完整度(如果羊毛团队没有花大功夫来抹特征的话)(可以上机器学习)
8.准备一套不同的请求流程,等上线之后突然打开(也是为了方便的摘出异常的客户端行为)
9.Browser端算token验证请求合法性(我知道没有什么卵用不过复杂一点也算是能增加对方成本了)

说了那么多其实就几点:提高对方成本,降低己方成本,完善监控尽量止损

然后前脚刚挂电话,后脚就听ere说我凉了;w;

长亭
=
长亭跨界招聘的一个计划...
所以问的东西基本上感觉是在问基础掌握到哪个程度了

问简历里最大的项目写过哪些语言,使用频率从多到少都说了一下
数学、算法、数据结构如何(问了汉诺塔怎么解,冒泡快排怎么写,堆和栈的区别)
写过的项目代码量有多大
自己感觉自学掌握到什么程度了
官网上说主要开发语言是Python却没有问Python emmmm....

不过电话打得真准时,好评)
面试官也很温柔233

然而完全没有算法基础,甚至学校连数学课都没有,回答汉诺塔的时候,面试官感觉也很尴尬...
最尴尬的是,问到一半突然电话被挂掉了....打电话过去也没人接,等了一个小时hr回了一个电话,说没有合适的岗位;w;

DaoCloud
=
感觉终于能平常心面对面试了o.o

初试
-
一开始开门见山的说明了招人需求,真棒
通话质量有点差,全程都在认真的想办法听清楚面试官说什么233
似乎是招面向客户的部署人员支持人员,查了一下官网,似乎指的是“客户交付”,感觉是售后服务的角色(感觉还行)
全程感觉围绕着简历在一项一项的确认是不是真的2333

简单的问了一下:
tcp,udp的区别
接口和类的区别
进程和线程的区别
hash算法
hash表
会不会 Powershell
bash和cmd感觉区别在哪里
git了解到哪个程度,会不会git flow(一开始还不太清楚git flow是什么,一查才知道原来是自己一直在做的事情233)
两个链表求相交
你简历里面写的“非常规DevOps是什么”(一把梭哈哈哈哈)
C#的GC了解过吗

然后问了问“你写C#写得多,如果进来了写go有没有问题”,答曰没有问题(不是...那问我C#干嘛...)

全程比较轻松愉悦,好评

复试
-
电话一接通,复试的面试官那极度疲惫的感觉扑面而来。
看来工作真的很辛苦啊(感觉身体被掏空)

开门见山的介绍了业务的技术栈
“基于winserver的docker服务部署,然后对客户进行指导之类的...”
等一下,怎么感觉就是配环境的苦力....
面试官:“你看你对这方面有没有兴趣...”
我:"没有"
面试官:"........"
我:“那个...其实还是能接受的..”
面试官:“你不要勉强自己...”

于是再确认了一遍是什么样的岗位,虽然没怎么听明白,不过好像并不是纯体力活,有点放心)

面试官:“毕竟客户也有自己的运维的....”
我:"哦哦....是我误会了哈哈哈.."(尴尬)

然后感觉面试官硬着头皮继续问了下去....(我错了..)
对docker了不了解
网络方面了不了解
对winserver配置了解的多吗
做项目平时都是自己写代码没有多人协作过么
自己一把梭的简单部署方案和成熟的DevOps系统比,有什么优缺点(说了一下拓展性,学习成本,部署难度)
遇到过什么困难(二进制学习曲线太陡峭了啊...)
为什么简历上都是信息安全的经历
Wifi钓鱼的思路,有没有办法干掉真正的Wifi(Deauth flood)
进来不写 C# 写 Go有没有问题
对这个offer期望大么
实习留任有没有想法

感觉连挂三家之后要起死回生了?

三试
-
这一面主要问了虚拟化方面的东西
对 Docker、虚拟化的了解,以及关于虚拟化的cli命令(然而只用过gui)
然后问了问 Restful 有没有用过

因为并没有研究过这方面的所以很快就结束了。

对于我来说,可能这次面试只是把之前的工作内容再确认了一遍

四试
-
好像是 CTO 面的
问了会不会 Restful
做过什么东西,用了哪些语言,是如何实现的。
网络方面,DHCP,ARP,二层三层什么的。

然后就拿到了年轻人的第一个 Offer 了。
感觉这四次面试真的每个面试官都问了不少重复的问题233

360
=
一面
-
吃黄焖鸡吃到一半来了个北京的电话,好像是开发岗的姐姐面的。(也很疲惫的样子)

先是问了一下网络方面,依次问了 HTTP,TCP(握手,通信),IP包头内容,ARP,Socket
Socket 异步怎么写,epoll,select什么的...(没在linux下面用过,windows常用的就只有select的,类epoll的还没有用过)
HTTP header 有些什么东西
不知道HTTP请求长度,也没有 Content-Length 的情况下怎么做 parse (答了一个chunk)
gzip算法实现(并不会)

进程间通信几种方法
多进程架构要怎么共享资源(提示了一下父子进程关系,难道说的是fork)
死锁的原因
内存泄露怎么排查原因

huffman tree
链表怎么知道有环
怎么找集合中出现了一半以上的元素
快排,二分查找

做过什么项目,觉得有什么亮点

如果要给线上运行的业务加功能,会有哪些方面的顾虑,会如何去部署新版本(感觉这个问题很好玩)

二面
-
部门老大面的,全程都在笑很开心的样子

自我介绍
实习经历,项目经历
问了问安全相关的项目
渗透都是怎么学习的
反汇编
什么时候开始写代码
大概写过多少行代码(我一直觉得这问题挺没有意义的...)
单例和工厂模式

然后介绍了一下部门和工作内容

hr面
-
和hr小姐姐聊天,最后确定offer啦

其他的一些事情
-
总的来说,工作内容还是觉得daocloud那边更好玩一些,docker,kubernete,inband的一些管理之类的开发....
不过360大啊,大啊...大啊....啊.....hhhh

这两天想把基于 Flask 的 Telegram Bot 重新写一下,之前一把梭的太难看了。
顺便把一直想写的插件系统实现一下,这里单独把插件部分摘出来记录分享一下

./main.py

from flask import Flask, request, Response
import os, sys

app = Flask(__name__)
app.debug = True
sys.dont_write_bytecode = True

# 插件部分
print("Loading plugins...")
sys.path.append(os.getcwd() + '/plugins')  # 设置一下 module 的搜索路径
plugins = []
for file in os.listdir("./plugins"):
    filename = file.split('.')[0]
    plugin = __import__(filename)  # for 起来 magic 一把梭
    plugins.append(plugin)
    print "Loaded Plugin '%s' with priority %s." % (filename, plugin.priority)
plugins.sort(key=lambda x: x.priority)  # 一个一把梭的插件优先级实现
# 看一看最后 EventLoop 的处理顺序
print("Plugin order:")
for plugin in plugins:
    print(plugin.__name__)
print("Plugins ready.")
# 业务部分
@app.route("/")
def index():
    # EventLoop
    for plugin in plugins:
        plugin.plugin_main(request.data)
        if update.handled:
            print("meet handled, stopping EventLoop.")
            break
    return ""

./plugins/example.py

#!/usr/bin/env python
# coding:utf-8

priority = 100

def plugin_main(update):
    # Do something...
    update.handled = True  # 阻止优先级更低的插件接收到 request

if __name__ == "__main__":
    print("This is a plugin.")

终端输出

(.env) [email protected] /h/w/api.stone.moe> python dummy.py
Loading plugins...
Loaded Plugin 'msglog' with priority 0.
Loaded Plugin 'example' with priority 100.
Loaded Plugin 'cmdhandler' with priority 1.
Plugin order:
msglog
cmdhandler
example
Plugins ready.
 * Running on http://127.0.0.1:8081/ (Press CTRL+C to quit)

新增用户时指定用户所在的 Group

# ocpasswd -c /path/to/passwd/file -g "groupname,groupname2,groupxxx" username

ocserv.conf 里面几个关键配置

# 关掉自动选择
auto-select-group = false
# define 几个 group identify,bracket 里面可以写点description
select-group = all
select-group = aws[no bracket or add some description]
select-group = nochn[No CN route]
....
# 指定一个存 config-per-group 的路径
config-per-group = /etc/ocserv/config-per-group/

然后我们

# mkdir /etc/ocserv/config-per-group
# cd /etc/ocserv/config-per-group
# touch all aws nochn

然后在这几个文件里写上config,来覆盖掉 ocserv.conf 主配置文件的设置。
比如在 nochn 写上一点 no-route。
也可以在 aws 写上一些 route,让这个组的用户在连接后只接收一些到 aws 的 route table。

HTTP 本身,POST body是不限格式的。

然而没有标准怎么行,于是有好几种 Content-Type 和 encoding 方案给 POST 用。

0x01 HTTP 本身的编码相关问题
-

  1. HTTP spec 规定
HTTP Header 必须为 ASCII 编码

但是规定虽然是规定,还是得看BS两端具体能不能容错,再说 unicode 也兼容 ASCII,所以大部分时候没什么毛病。

(不过我们最好还是遵守 spec)

  1. 与 charset 相关的 header 有 Content-Type 里面的 charset 属性

    一般这样写:

Content-Type: text/html;charset=utf-8

似乎是指 Header 虽然要求 ASCII,可是 entity body 却可以指定其他编码(可能会要求兼容 ASCII)。
这部分读 spec 也没看太懂,期待大神指教。

0x02 再看 POST
-

几种常见/常用的 POST entity body Content-Type

application/x-www-form-urlencoded
multipart/form-data
application/json

然后从 Postman 里面又看到了几种平时没怎么见过的或者不常用的

text/plain
application/javascript
text/xml
application/xml
text/html

看到这里其实就明白了,归根结底还是来源于 MIME (rfc1341)

0x03 常见的 POST 都长什么样子
-

1.application/x-www-form-urlencoded

大概长这样:

POST /abc HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8

title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3

最基础的 HTML Form 提交之后,浏览器就会使用x-www-form-urlencoded,是默认的表单格式。

除了 Header 指定的 Content-Type 之外:

  • 格式为 key=value&x=y
  • 使用 urlencode 编码
  • a[]=abc&a[]=123 可以用来表示 array

2.multipart/form-data

大概长这样:

POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=AaB03x

--AaB03x
Content-Disposition: form-data; name="submit-name"

Larry
--AaB03x
Content-Disposition: form-data; name="files"
Content-Type: multipart/mixed; boundary=BbC04y

--BbC04y
Content-Disposition: file; name="forminputname" filename="file1.txt"
Content-Type: text/plain

... contents of file1.txt ...
--BbC04y
Content-Disposition: file; filename="file2.gif"
Content-Type: image/gif
Content-Transfer-Encoding: binary

...contents of file2.gif...
--BbC04y--
--AaB03x--

给 Form 设置 enctype="multipart/form-data" 之后,就可以使用 multipart 格式来上传文件了。

除了 Header 指定的 Content-Type 之外:

  • Content-Type 后面跟了个 boundary 属性来声明 multipart 的边界,作为多个 Form input 的分隔符
  • 每个部分的起始分隔符前面要加--
  • 每个部分的结束分隔符前后都要加--
  • 每个部分都能指定 Content 相关的 header,甚至能继续嵌套 multipart
  • 通过 Content-Disposition 提供 Form input 的 name 属性

这部分比较复杂,可以参考 SOF

3.application/json

大概长这样:

POST /efg HTTP/1.1
Content-Type: application/json;charset=utf-8

{"title":"test","sub":[1,2,3]}

没什么好说的,简单,好用。

如果BS两端都支持的话,非 ASCII 编码并不需要额外编码,JSON 本身并没有要求。
但通常为了更好的兼容性,会使用编码后的形式,而这里就是跟 javascript 的 escape 走了,并不是urlencode。
而编码后也很简单,直接使用 unicode,如 "\u0421\u043b\u043e\u0432\u043e",或者 "%u0421%u043b%u043e%u0432%u043e"