ICKelin

Results 17 issues of ICKelin

## 面对的问题 在访问一些海外网站或者海外应用时,通常会遇到访问慢的情况,访问慢有两个原因,一个是丢包,一个是线路拥塞。当然还有其他一些原因,比如说运营商劫持或者防火墙拦截的情况。当你在跨国企业时,这种现象就特别严重,比方说,你们公司的数据中心在美国,而你的客户端在需要与数据中心交互获取最新的数据,这时候再丢包就影响心情了。所以,很多时候,我们会加个类似”跳板“之类的东西来加快我们与数据中心的交互速度。 ## 加速器 很多人理解的加速器仅限于网游加速器,简单来说是玩外服游戏时特别卡,丢包严重,延时严重,需要一款加速器来让我们游戏数据走加速线路出去,而加速线路给他们解决来丢包和延时的问题。但是我认为加速器应该有更大的用途,可以加速应用,游戏也是应用的一种,当然也访问一些在国内无法访问的网站。 ## 加速器原理 目前了解到的所有加速器基本都是一个原理,将客户数据通过一条高速通道把数据流引到某台服务器A,A与最终需要访问的应用应该足够稳定,丢包和延时都比较好,然后A再将用户的网络数据包发送给目的服务器,并且将结果原路返回,最终回到客户电脑,简单来说中间整个过程都是 **代理**,把数据送出去再送回来,参考下图。 ![image](https://user-images.githubusercontent.com/9639491/33610971-d75e63e6-da07-11e7-9d96-e292eafd40d4.png) 这里面的难点都在tunnel上,而tunnel上又可以继续细分下来。 在了解tunnel之前,需要知道两点 1)tcp协议在长距离传输丢包会非常严重,从大陆地区到香港某些时刻会丢包丢到怀疑人生 2)运营商对udp数据有歧视,参考[udp2raw](https://github.com/wangyu-/udp2raw-tunnel) 之前提到,tunnel的目的就是将数据送出去再送回来,那么会碰到第一个问题,数据从哪里来。 因此,我们需要采取一种措施将数据导向我们tunnel的入口。措施有很多种,每个系统都不太一样,我接触的大致会有一下几种方式 第一种,通过网关的方式,所有数据都会经过网关外出,如果你有一个硬件,可以是树莓派或者其他,接入正在使用的网络,然后开放ap或者手动设置网关或者dhcp的方式,接入的所有设备的网络数据包自然就会到达网关来。 ![image](https://user-images.githubusercontent.com/9639491/33665944-6ce18008-dad3-11e7-999d-3de15caf117c.png) 这个图片非常抽象,我觉得需要加以说明。首先我们的设备gateway(这里假设是树莓派)和用户接入共同的网络,可以认为他们连上同一个热点,在一个局域网里面,但是,修改pc的网关指向我们的树莓派,这样pc上的网络数据就会经过我们的树莓派出去,我们就可以在树莓派上对数据包进行处理,决定哪些数据包应该进行何种操作。这是一种通过网关的方式。 第二种是编写客户端,这种很容易理解,每个pc上运行有一个客户端,客户端可以决定哪些数据包应该进行何种操作,实际上,第一种方式也可以认为是一种客户端,但是同时也是pc的接入点,他可以接入多个pc的请求,相当与路由器。具体如下图 ![image](https://user-images.githubusercontent.com/9639491/33666724-d98fbc86-dad5-11e7-8ae7-7f47821cc462.png) 这其中pc出口后面的线路省略。 还有第三种,不用编写客户端,也不用搞树莓派,通过vpn+接入程序。好处是不用额外的设备,也不用针对各个平台开发客户端,只有云服务器,缺点是如果vpn使用系统自带的,如果走的是udp协议,在运营商这块可能就会被卡住,还有就是可能会牺牲一点性能。 ![image](https://user-images.githubusercontent.com/9639491/33667082-d1f93780-dad6-11e7-9fc5-72203dab2b3d.png) 这三种引流方法相对比较容易实现的是第一种,当然第一种实现了之后,第三种基本上就实现了,第二种由于平台之间的差异性,实现难度不小的。还有其他方式可以进行引流,可以设置pac和一些类似socks之类的代理,但是无法做到全局代理,如果某个应用不走域名,直接走ip,而且走的是tcp或者udp协议,那么这类应用将无法加速。 接下来针对这三种方式的一些技术内部做一些描述 ### 网关设备 ![image](https://user-images.githubusercontent.com/9639491/33665944-6ce18008-dad3-11e7-999d-3de15caf117c.png)...

DNS是非常常用的网络基础设施软件,但是如果不是做软件开发的,很多人都接触不到,很多做应用开发的,可能接触DNS服务器的机会也不多,但是不管怎样,DNS是非常非常非常重要的网络基础软件。 这篇文章记录了对DNS的一些基本理解以及在[notr内网穿透](https://www.notr.tech)当中使用到的非常重要的动态域名解析这一功能。 ### DNS解决什么问题 需要明确的一点,互联网上的通信寻址是通过ip地址来寻址的,打个比方,如果从你的电脑上ping 1.1.1.1,首先判断1.1.1.1是否和你处于同一个子网,如果属于同一个子网,则按照内网通信的基本流程,先进行ARP广播,查找ip地址为1.1.1.1的mac地址,然后通过mac地址进行通信,如果不属于同一个子网,则也要先进行arp广播,不过查找的是网关ip地址的mac地址,将数据包发给网关,网关匹配路由之后,继续转发给他的上一级路由,依次迭代,直到到达1.1.1.1所在的机器。 如果纯粹使用ip地址通信,通信是没问题的,但是互联网发展太快了,五六年前的规模和现在完全一个层面,五六年前,我还在学jsp,学MFC,现在MFC也叫没饭吃,设计互联网的人很早就想到了这点,ip地址太难记了,要记住所有网站的ip地址显然是不可能的,所以他们设计了域名系统,在ip地址与域名之间构建一个映射关系,通过域名关联到ip地址,然后用户只需要记住域名即可,记住www.notr.tech总比记住120.25.214.63要容易得多。但是这又会产生一个问题,用户每次访问www.notr.tech的时候,都需要先通过互联网获取到www.notr.tech的ip地址,每个域名相对直接使用ip而言,都多了一步域名解析的步骤。于是为了加速域名解析的过程,DNS服务器都会设置有高速缓存,不仅如此,每台电脑针对域名查询,也做了高速缓存,不仅如此,有的浏览器内部也做了域名高速缓存。所以就有了如果某浏览器是带有dns缓存功能的,访问一个网站时,首先从自身的缓存看有没有记录,如果有,直接用,如果没有,看系统DNS缓存是否有记录,如果有,直接用,如果没有,发起DNS查询,如果刚好你的网关配备有DNS服务器,而且dhcp服务器给你电脑下发的DNS就是你的网关地址,那么你的网关先从自身缓存查,依次迭代下去,所以,DNS缓存提高了域名解析的效率。 ### DNS基本流程 DNS采用UDP协议进行交互,交互可以归纳为下面的流程 ![image](https://user-images.githubusercontent.com/9639491/43031242-520a31da-8cd0-11e8-9d88-d4a9d7cc92a4.png) 这里将DHCP也纳入其中,DHCP跟DNS的关系仅仅是:PC启动的时候会发送DHCP请求广播,DHCP服务器收到这一广播之后会响应,会告诉PC,你可以使用a.b.c.d这个ip,网关地址是a.b.c.1,DNS地址为1.1.1.1之类的信息。这个很重要,可以通过DHCP控制所有用户电脑的网关和DNS,也就是说可以将下发的网关和DNS指向它自身,然后所有流量和域名查询都经过它。 dns服务器本地无缓存时,会不断迭代同一个过程,以yingjiu.notr.tech为例先找到根服务器,询问是否有yingjiu.notr.tech的ip地址,根服务器响应没有,但是你可以到ns1.china.com去查询,ns1.china.com的ip地址是xxxxx。于是本地dns服务器向ns1.china.com进行域名解析,ns1.china.com发现本地也没有相关的A记录,但是有个ns记录,记录值为ns.notr.tech,于是ns1.china.com响应给本地dns服务器,告诉它,我没有相关记录,但是我知道谁可以解决你这个问题,你可以到ns.notr.tech进行解析,ns.notr.tech查本地记录,发现有对应的记录值,于是响应该记录值,本地DNS服务器拿到域名解析的结果之后,响应给pc,最终完成域名解析。 DNS服务器实现有许多细节,但是如果业务需求不复杂,可以考虑从以下两个角度进行简化 - 只实现A,AAAA,以及NS记录 - 只实现dns代理,域名解析交给上游,只需要知道,上游返回的结果肯定是可以返回给pc的。 ### 动态DNS 以下内容摘自百度百科: 动态域名解析服务,是将用户的动态IP地址映射到一个固定的域名解析服务上,用户每次连接网络的时候,客户端程序就会通过信息传递把该主机的动态IP地址传送给位于服务商主机上的服务器程序,服务程序负责提供DNS服务并实现动态域名解析。就是说DDNS捕获用户每次变化的IP地址,然后将其与域名相对应,这样域名就可以始终解析到非固定IP的服务器上,互联网用户通过本地的域名服务器获得网站域名的IP地址,从而可以访问网站的服务。 简单理解动态DNS即为:当DNS具备能够动态添加,删除,修改某个域名记录之时,就具备动态DNS的基本能力。 打个比方:你在使用某个动态DNS服务,你配置家庭出口路由器映射的ip地址映射到router.home.me,但是家庭路由器每次启动时ip地址可能会发生修改,原因是运营商之前下发的ip地址可能被分配给其他用户,所以这时候如果DNS不具备修改的能力,那么访问router.home.me解析到的ip地址即为其他客户的ip地址,这时候就需要DNS能够提供一个接口让家庭路由器感知到ip地址发生了改变,将router.home.me的值进行相对应的调整。也就是做router.home.me这个域名的修改操作。 所以在无固定ip地址的情况下,采用动态DNS具备一定的用处,这里介绍我动态DNS的使用场景: [Notr](https://www.notr.tech)是一款内网穿透服务,其中动态DNS占了非常大的作用,客户端每次分配的域名是固定的,但是域名映射关系每次都是不固定的,因为我内部需要根据当前各个节点的使用情况与负载进行动态调整,选出一个节点为该客户端提供内网映射的接入口。具体可以参考Notr时序图NotrController与NotrNs交互 ![image](https://user-images.githubusercontent.com/9639491/43034086-241b9808-8d08-11e8-9a94-60cf7485a980.png)

上周需要针对当前版本的加速隧道添加ipv6的支持,这也特别符合我们程序的理念,我们程序就是一个隧道,所以如果隧道起点和终点协议不需要进行调整,那么就需要在起点与终点处添加对ipv6的访问支持即可。事实上只需要在隧道的终点添加ipv6的支持即可。 目前国内运营商不支持ipv6,需要访问ipv6地址需要另外进行处理,在内网环境可以通过一以下方式进行。 ``` 1. sudo apt-get install miredo 2. 以root权限打开ufw的配置文件: “/etc/default/ufw”,找到”IPV6=no”这一行,将其改为”IPV6=yes”。 3. sudo invoke-rc.d networking restart ``` 在公网当中,可以通过如下方式进行ipv6参考[阿里云ipv6](https://ilazycat.com/posts/2016/12/aliyun-ecs-ipv6-configuration.html)

本周在网关上解决一个网卡分流的问题,简单可以描述为tcp数据走eth0,udp数据走eth1,icmp数据走eth2。研究了下,发现可以利用**iptables的mangle表和策略路由**来进行流量分发。 在了解iptables之前,我觉得应该首先了解下数据包在内核路由子系统前后会经过那些处理以及linux防火墙里面非常核心的netfilter系统。 ![image](https://user-images.githubusercontent.com/9639491/34916220-8535f610-f96f-11e7-9c25-cde9821478ac.png) 这上面是netfilter系统非常典型的几个钩子处理,本人最初接触netfilter的时候是在学校的一次大作业当中开发的一个包过滤防火墙,职业辗转,最后还是回到来netfilter相关的技术,当然也没有这么底层了,更多的谁在用户层徘徊。 在了解netfilter之后就得开始考虑netfilter和iptables之间的关系了,netfilter可能很多开发人员接触的不多,但是或多或少了解过iptabes,其实很多人说iptables是linux下的防火墙,这个说法我觉得不太合适,iptables是linux防火墙的一部分,简单理解iptables其实只是防火墙的前端,给用户用的,还有就是给内核模块发送规则操作命令,真正实现防火墙功能和维护规则表的其实是内核模块。 ### iptables的四表五链。 四表:raw,mangle,nat,filter四表 五链:也就是上图当中的PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING五个hook点。 链和表的关系是1:n的关系,一个hook点上可以有多个表,此时就有一个表的优先级的问题,四表的优先级分别是 raw>mangle>nat>filter 表和链的关系是一个hook点上可以有多个表,具体对应关系如表1所示: 表1: | table | hook | |--------------|------------| | raw | PREROUTING,OUTPUT | | mangle | PREROUTING, INPUT, FORWARD,OUTPUT,POSTROUTING|...

在项目当中有时需要连接跟踪相关的信息,netfilter官网提供了一个libnetfilter_conntrack的用户态库,通过netlink的方式与内核对应的模块通信操作conntrack,但是会有性能瓶颈,还有就是问题不好定位,本文提供一种用户层获取连接跟踪的实现思路,在继续阅读之前,请确保具备以下基本知识: - 了解netfilter - 能够开发基于netfilter的简单的包过滤防火墙 - 对skb有一定的了解 解决思路很清晰,在内核层面netfilter钩子当中hook数据包,然后强行在L4和payload之间封装一层协议,有点类似运营商植入广告,将连接跟踪的信息通过这层协议传递给用户态,用户态先解这层协议。再读取数据。 比如说,用户层比较关心DNAT之前的目的地址(origin_ip)和目的端口(origin_port),那么可以将origin_ip和origin_port再加上payload的长度三个字段作为一层协议,插入到tcp和payload之间。这样用户层的应用只需要正常读数据,读取协议头,再读取payload即可。 以TCP为例,部分示例代码如下: ```c // tcp static int handle_tcp(struct sk_buff *skb){ struct iphdr *ip = ip_hdr(skb); struct tcphdr *tcp = tcp_hdr(skb); // conntrack...

趁着过年有空闲时间做了个小项目,其中有一小部分功能是网络流量可视化,能够在世界地图上显示网络流量的情况,这里面需要解决一个问题,就是根据网络ip地址能够定位到具体的经纬度,经过一番查询,最终决定用 [freegeoip](http://freegeoip.net/) 的api来进行。百度的ip地理位置有数量限制也是就舍弃了。但是用了百度的[echarts](http://echarts.baidu.com/)作为流量显示组件。目前效果大致如下。 ![image](https://user-images.githubusercontent.com/9639491/36338132-ea384f22-13e1-11e8-9933-882557c830d7.png)

眨眼之间,从大学毕业至今已将近两年,两年时间从学生转变成一个可以适应职场生活的上班族,经历了很多人,很多愉快的不愉快的事,自身也发生了非常多的转变,但是似乎没有做过一次非常系统的总结,特此一文,总结一些职场当中的收获。 首先是非技术方面,在创业公司待久了之后会发现其实大部分创业公司死的原因其实在于管理,大部分员工跳槽最主要的原因是上司,而管理是非常考验人的管理理论,情商,观察力,分析力以及沟通能力的一项技能,** 从而提高下属的工作兴趣,工作效率以及降低其离职率 **,感觉又非常的复杂,有意思。所以在非技术方面,我会回顾自己经历的上司,自己一些失败的经历来叙述每一个总结点 ## 不要跟风喷产品经理或者游戏策划 这个被我列在首位,因为我曾经也跟风喷过策划。很多新手程序员(当然我也还算在新手村里面待着的),在没进入这个行业之前可能听过很多关于程序员和产品经历之间的各种段子,于是对产品经历产生了抵制,跟着转发一些趣图,段子之类的,这是非常不可取的,我还记得我刚毕业的时候微信头像是一群人围着策划开枪的图片,现在想想真是无知,你要知道,在工作当中,做产品的和做研发的很有可能会频繁的交互,沟通协调,如果带着一种消极的心态,是非常不利于沟通的,而且,试问和你沟通的你口中所谓的“产品狗”,如果看到你朋友圈转发的趣图,他会觉得有趣吗?很多问题都是可以进行友好的沟通解决的,要认真听取和分析,不合理或者有分歧的地方可以再讨论,很多东西都是可以讨论进行解决的,只要具备足够耐心。 ## 做好一个倾听者 倾听应该算是我个人最看重的一点,(其次是谦虚,这两点应该算作一点了),我刚毕业的时候在一家游戏公司待了一段时间,当然最后选择了离职,离职原因不在公司,最主要的是我个人身体问题,加班实在是太严重了,我这边身体完全吃不消。但是当时的上司人非常的好,非常赞的一个leader,我现在很多观念应该都是受他的影响,其身上最出色的有点应该就是会聆听,人与人之间说不通话我个人认为最主要的原因是他会认认真真等你把话说完,不要以为这是一件很简单的事,实际上,这非常的困难,这是非常高情商的一种表现,至少后面我经历的大部分同事都存在打断别人话,他们或许认为已经理解对方要表达的意思了,其实并没有的,最后还需要手动说一句,你先听我把话说完,但是即使是这样子,还是会存在其他问题的,比如说,对方很有可能会认为你听了他插入的描述之后立马转变自己的枪口,听你把话说完。所以说去完完整整听对方把话说完,这个本身就并非一件容易的事了。很多人之所以成为不了一个领导者或者一个好的领导者,这项能力是非常重要的,你要做不好,真的就别怪下属跳槽。就我个人而言,无论是工作还是生活当中我都是一个非常安静的一个人,以至于很多人觉得我很闷,和不合群,半句话不离工作,大概是我个人性格的一项重大问题,这点想修正其实非常难,除非人生再经历非常大的波折,想想还是不要了,哈~ ## 注重Team Work 这里记录一个我前上司的故事,前上司,也是我目前公司的前CTO,个人能力挺强,可能跟人生经历有关,作为it届的老人,我很尊重他,跟他沟通能够了解到整个行业变化的历程。但是仅限于此,要想一起出去创业之类的,我绝对会说NO的,倒不是我现实,只是我不太喜欢跟个人英雄主义太强的人合作,如果我是一位领导者,我二话不说要开的肯定是那些无法跟同级成员合作的下属,即使你非常的聪明,我觉得并不缺乏聪明的人,但是我缺乏能够一起做事的人。而且回过头想想,真的有这么多聪明的人吗?不见得的。 在此我表明我个人关于聪明的两个观点 1)如果你是上司,不要公开说自己某个下属非常聪明,没有好处,只有坏处 2)如果你觉得自己挺聪明的,大家好像也都是这样觉得,请收好这颗心,他很有可能会害死你 ## 不要自己做一个项目 如果一个项目是需要自己一个人做的,我会立马跟上司表明我的观点,这个非常不利于团队协作能力,作为上司,也尽量不要安排人员独立完成项目,很有可能项目完成之后你会失去一个同事。 ## 如果你是一个领导,记得跟底层员工多交流 尤其是在创业公司,很多创业公司的老总非常的有人脉,想法有行动力甚至资金,但是最后却失败,回头想想为什么,或许你怎么也想不明白,但是换个角度去思考,你的员工肯定知道,他们一天到晚就待在公司,跟公司的人接触,跟公司的项目接触,跟客户接触,他们有非常切实的感受,肯定有很多员工是非常了解企业的问题和不足,但是他们不会跟你说,你要记住这点,他们很多是不会跟你说的,第一点你不是他们的朋友,第二点他们怕得罪人,毕竟他们也只是混口饭吃而已,第三点他们为什么要告诉你,这点很可笑,但是会存在,简单来说他们本来就是基层,随时都可以换份工作,这对他们来说是工作不是事业,他们很明确的知道自己是来学习技能和积累经验的,你公司发展怎么样他根本就不关心,他们接触不到boss这一级别的,boss对他们来说是透明的,从入职到离职,都没有和boss有过任何交流,怎么可能会突然敲你门然后给你提意见。或许离职的时候会稍微敞开一些跟你表明,但是要知道,离职很多人也是追求你好我好大家好,凡事留一线日后好相见的态度。如果不常跟他们交流,你也许根本就不会知道也许你自己公司内部已经糟糕到不能再糟糕了,很多员工都在准备跳槽,当新的一波招聘过来的时候,也许你回头发现公司已经所剩无几了,这时候真的就无力回天了。 ## 管理人事一件非常困难的事 人员用不好,那整个公司就完来,技术选不好还有得补救,中层领导选错了,那就别忙活了。因为你会收到来自中层领导的错误的讯息,这些错误的讯息会引导你错误的看待事情,我记得在本科一门管理学课程上有过一个案例,大致意思应该是一句话从底层员工,到经理到总监最后再到总经理,整个过程当中每一步都会有存在消息的遗漏或者出于其他目的替换,最终消息到达总经理手上完全是另外一个描述了。我本科获得的是管理学学位,所以我对管理的带来的重大意义会有更多的一些感受。 非技术上还有非常多的一些体验,都是从我自己身上,从同事身上,从上司身上看到的优缺点,其中负能量居多。在技术上,体会尤其深刻 ## 先做好工作,再想其他 很有幸在碰到一些认为工作当中无事可干的朋友,慢慢沟通会发现,其实他们并非无事可干,只是不喜欢干工作项目,觉得没有意义,学不到东西,浪费时间,再进一步沟通,你又会发现,他们本身工作范围内的项目其实也没有做好,然后又想做一些自己感兴趣的,觉得牛逼的事。但是相信我,他们很快又会对他们之前觉得有意义的事失去兴趣,这一现象在IT行业有一个出现频率非常高的词,叫**...