关于docker

  1. docker create -it 其中 -it选项,如果没有的话,docker exec 进去,top时会报 TERM environment variable not set. 错误 ; 其实没有关系,手动 export TERM=xterm-256color 就可以了;其实, -it 选项和1号进程为 /bin/bash 是密切相关的; 如果1号进程不是 /bin/bash 的话,-it选项没有屁用
  2. docker 的CMD 其实是1号进程,一定不能立即就会退出的进程,如: service sshd start 就不行,如下脚本就可以:

     
  3. 容器可以自杀: 容器内进程使用root kill -9 1 默认是杀不死1号进程的,但是:
    当strace -p  1 的时候,kill -9 1 是可以杀死1号进程的 (难道说这是个bug?)
    因为docker stop时是先给1号进程发送sigterm,是在不行才kill -9 ; 所以,1号进程最好能合理处理sigterm信号,最后退出;然而,容器内的root进程是有权限给1号进程发送sigterm信号的,所以,容器自杀其实是很方便的
  4. 改进版的1号进程
    myinit.c

    gcc -o myinit myinit.c
    myinit.sh

  5. 其实还不够
    你会慢慢发现,ssh连接失败,因为:sshd接到连接请求之后,检查是否session太多了(默认最大10个),超过了就不伺候了,直接断开; 为什么会太多了?sshd每次接到连接请求,会fork => fork (两次fork)出来一个子进程处理请求,就因为是两次fork,这个新的sshd进程便“过继”给了1号进程;但是上面的1号进程还不够成熟,不会带孩子,当这个新的sshd进程退出的时候,就需要1号进程来做一些处理(如:清理进程表项),但是1号进程还不会,于是新的sshd进程会处于 <defunct>状态;而sshd的祖先还以为该session还没结束,就不再接受新的请求了,解决办法:添加信号处理,如下:

    参考资料:
    https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/
    https://github.com/phusion/baseimage-docker/blob/rel-0.9.16/image/bin/my_init
    dockerd 提供了init 和init-path的选项,允许配置是否启动一个指定的(默认的)init进程, 该进程就是为了转发信号和收割僵尸进程 的
  6. 上面sshd对于连接请求是两次fork的说法不太对,见下图:

    99、134进程并没有立即退出(不过,一旦意外退出,则 101、136将会被1号进程收养)
    还有一种情况为:sshd被restart了,这时候30号进程退出,99、134被1号进程收养,如下:

    由于我重启了sshd,再次连接就会失败,如下:

    为什么呢?
    稍后再查,至少可以确定的是,启动容器时候启动的sshd是可以正常服务的,登录进去重启的sshd是不能正常服务的

 

see also : https://docs.docker.com/engine/examples/running_ssh_service/

 

关于docker的内存限制:

  1. 如果每个docker容器限制最大使用4G,则可能会使用超过4G,(似乎是使用了交换分区了)
  2. 如果宿主机有64G内存,则允许docker容器内存总和大于64G,(这个不会也和交换分区有关吧)
  3. 文档说–memory-swap=-1 就禁止使用交换分区了,但是测试发现还是使用了1倍内存的交换分区

缅怀一下阿里云云引擎

 

学习一下人家下线产品是咋写的:

 

关于httpdns

概要

httpdns就是通过http的方式进行域名解析;阿里云有提供httpdns服务(目前2016-4-9 还处于公测阶段,需要申请公测资格才能用)。

传统dns解析存在的问题:

  1. 由于传统dns解析采用udp方式,而且是明文,所以
    1. 可能会被篡改
    2. 可能会被投毒(什么叫“投毒”?且看下文)

httpdns的实现原理:

  1. 通过http的方式进行域名解析,如:
  2. 通过设置http host header的方式发起http请求,如:

 

问题:

  1. httpdns server的域名如何解析?
    httpdns server 不通过域名提供服务,(只能)直接通过一个固定IP提供服务;服务提供商有足够的手段让这个IP不会出现宕机,而且世界各地(或者是全国各地)访问都能很快(就近访问),这个IP在世界上存在多份。
  2. 如何保证连接的这个ip是没被劫持呢?
    1. 或许可以给这个IP买个https证书,https证书提供商是可以给IP颁发证书的(比较少见),不过可能贵的多

 

优点:(参考文档: https://www.aliyun.com/product/httpdns?spm=5176.7960203.223922.4.2JohAO

  1. 防劫持
  2. 避免dns服务商莫名其妙的cache,可以做到立即修改理解生效
  3. 精准调度

问题:

  1. https请求问题及解决方案: https://help.aliyun.com/document_detail/httpdns/practice/https.html?spm=5176.7947101.220063.5.9DtXGS
    1. 这里回避了单个IP上多个https证书的问题,或许也可以通过钩子解决,但是不一定存在这样的钩子; ssl握手的时候,必须告知正确的host信息,否则,服务器无法知道该返回哪个证书,而不仅仅是验证证书的问题
  2. httpdns只适用于app、client的情况,对于web浏览器是不行的,还好现在大家都是在玩app了;
  3. 对于app里面适用webview的情况需要特殊处理一下:https://help.aliyun.com/document_detail/httpdns/practice/webview.html?spm=5176.dochttpdns/user-guide/resolve-stats.6.127.VFTz3N
  4. 对于通过react native来开发app的情况不知道是否方便使用

 

dns投毒:

因为域名解析是udp的,只要我已dns server的ip不断地向你的机器发送域名解析结果响应的话,你可能就会认为确实是dns server响应的结果;当然,有几个关键点需要注意:

  1. 用户确实需要解析某域名(一般来讲,解析完了会cache一段时间的)
  2. 伪造的响应里面是需要包含用户正在查询的域名的,域名不匹配自然不会被接受
  3. 用户发起请求的端口号(2字节)是随机的,响应的数据包需要能匹配上这个端口,否则不会被接受
  4. 用户发起的请求有一个随机的请求标识(2字节),响应的数据包需要能匹配上这个请求标识,否则不会被接受
  5. 我咋感觉这个难度其实并不算小啊,除非你是个中间人

httpdns示例:

 

更多参考:

全局精确流量调度新思路-HttpDNS服务详解: http://www.zmke.com/i/8705.html

渗透测试:内网DNS投毒技术劫持会话:http://www.freebuf.com/articles/web/43157.html

http://www.onedns.net/  需要特殊的dns客户端

加密的dns: https://www.opendns.com/about/innovations/dnscrypt/   需要特殊的dns客户端

wireshark分析dns协议: http://blog.csdn.net/hunanchenxingyu/article/details/21488291

dns协议格式: http://cjhust.blog.163.com/blog/static/1758271572014111875652363/

关于shell一些小知识点

关于 [[]] 和 [] 的区别

实例1:

说明:

[]  和 [[]]  是不同的语法;

对于 [

事实上, bash 中没有 [] 语法, [ 是一个命令,出于美观考虑,要求有一个 ] 与之配对; 所以 [ 的前后是要有空格的

对于 [[

[[]] 是bash的内建语法

  1. 如果是 == ,则右边被视为 Pattern; 如果是 =~ ,则右边视为正则; 也就是说,左边和右边是不等价的
  2. [[]] 允许内部 与、或、非; 如: [[ 1 == 1 && 2 == 2 ]]; 而 [] 则不可以,只能: [ 1 == 1 ] && [ 2 == 2 ]

bash基本概念

  1. bash中有保留字(reserved word)和元字符(meta charactor)的区别的,这个很重要
    1. 关键字:
    2. 元字符:
    3. xx
  2. 对于关键字,和其他非元字符的字符都需要用空白字符分开,否则,关键字就识别不出来了; 因为元字符是被特殊对待的,所以,关键字挨着元字符是允许的,所以,如果分不清关键字和元字符的话,就不知道什么时候需要用空白符分隔,什么时候不需要空白符分隔

 

 

man bash

关于元字符、保留字

关于 花括弧

 

命令替换

 

 

docker虚拟机设置固定IP

参考文章: http://www.tuicool.com/articles/v2yQ7bA

创建网桥(可以写成一个脚本):

创建容器

稍微整理一下原作者的命令,写一个脚本:

注: 最新版本的iproute (至少在iproute-3.10.0-54.el7.x86_64 中)支持 -n 选项,功能为:

至少 iproute-3.10.0-21.el7.x86_64 中还没有该选项, 也就是说

等价于

 

如下br1是我做的网桥:

当docker容器stop时,这里的q7443也就消失了,但是网络名字空间中依然会存在; 可以通过 ip netns delete 来删除

 

一种情况,由于我的docker宿主机是virtualbox做的虚拟机,virtualbox虚拟机使用的桥接模式,所以,我这么做出来的docker虚拟机是访问不了外网的;因为,尽管docker虚拟机可以往docker宿主机的网卡上写数据,virtualbox的宿主机上的后台进程也不会发送该数据的(至少不会接受响应的数据)。

 

其实,有一个叫做pipework的工具可以很方便地给容器设置ip; 但是都没有提供卸载容器网卡的功能,有一种比较方便的办法: nsenter 进去 ifdown 就可以了

关于网桥

为什么virtualbox网卡桥接模式下在宿主机上看不到网桥?

virtualbox在后台启动了一个进程,很牛B,能从指定的网卡读取数据和写入数据,如此,就可以做到将某个虚拟机要发送出去的数据写入到指定网卡,而且网卡上收到的传给某个虚拟机(IP)的数据转发给指定虚拟机; 就这么简单。

参考: http://superuser.com/questions/594550/how-does-bridged-networking-work-in-virtualbox

 

 

dnsmasq 的一个小配置