一种 HTTP 会话劫持的防御方法

HTTP 会话劫持也是 TCP 会话劫持,它是利用了 TCP Seqnum 的可预见性来伪造有效的响应包,并抢先响应客户端同时使得客户端主动丢弃原服务器的响应包。在这个层面想区分哪一个响应包是伪造的是有困难的,但结合实际情况考虑问题也还有一些思路。

我们以劫持程序的设计者角度考虑:
1. 劫持程序不是什么都劫持了,只有符合条件被命中的 HTTP 请求才会劫持的,那也就是说劫持程序需要一个完整或至少包含它需要的信息的请求才可以劫持,我想 Host, QueryString, Referer 这些应该少不了。
2. 劫持程序不希望维护 TCP 上下文进行流重组。因为维护起来成本比较高。
3. 基于上一点来说,劫持程序也就不希望一个 HTTP 请求被拆分在两个或多个包中传输。

从实际检测来看,大多数的 HTTP 请求还是包含在一个独立的 TCP 包中传输的,只有很少的情况被拆分了。我想你一定想到了什么了,对!我们就假设当前在用的劫持程序都没有维护 TCP 传输上下文进行流重组,那么人为对前向链路上的流进行强制拆分,就应该能够逃过被劫持。

实现的方式应该会有很多,我在应用层代理层面实现了一个简单的原型,方式是将前向链路的 Buffer size 强制在了 16 字节。代码托管在 Github => https://github.com/heiher/hev-socks5-proxy/tree/anti-hijack

从抓包来看,HTTP 请求在传输时被拆分了:

packet 0:[syn]
packet 1: GET / HTTP/1.1\r\n
packet 2: Host: xxxx
packet 3: ...

Over!

Forward special packets

主机A与主机B之间建立了一条 IPIP 遂道,两个主机之间生成的TCP协议且源端口是8000的包需要通过遂道传输到对方后,通过对方的网关发送出去。

On Host A

TUN_IFACE="tun-b"
HOST_A_IP="10.0.0.3"
HOST_B_IP="10.0.3.2"
TUN_GATEWAY="192.168.4.2"
HOST_GATEWAY="10.0.0.1"
 
sudo iptunnel add ${TUN_IFACE} mode ipip remote ${HOST_B_IP} local ${HOST_A_IP}
sudo ifconfig ${TUN_IFACE} up
sudo route add -host ${TUN_GATEWAY} dev ${TUN_IFACE}
 
sudo iptables -t mangle -A POSTROUTING -p tcp -m tcp --sport 8000 -m mark ! --mark 0x8888 -j TEE --gateway ${TUN_GATEWAY}
sudo iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 8000 -j MARK --set-mark 0x8888
sudo iptables -t mangle -A PREROUTING -m mark --mark 0x8888 -j TEE --gateway ${HOST_GATEWAY}

On Host B

TUN_IFACE="tun-a"
HOST_A_IP="10.0.0.3"
HOST_B_IP="10.0.3.2"
TUN_GATEWAY="192.168.4.1"
HOST_GATEWAY="10.0.3.1"
 
sudo iptunnel add ${TUN_IFACE} mode ipip remote ${HOST_A_IP} local ${HOST_B_IP}
sudo ifconfig ${TUN_IFACE} up
sudo route add -host ${TUN_GATEWAY} dev ${TUN_IFACE}
 
sudo iptables -t mangle -A POSTROUTING -p tcp -m tcp --sport 8000 -m mark ! --mark 0x8888 -j TEE --gateway ${TUN_GATEWAY}
sudo iptables -t mangle -A PREROUTING -p tcp -m tcp --sport 8000 -j MARK --set-mark 0x8888
sudo iptables -t mangle -A PREROUTING -m mark --mark 0x8888 -j TEE --gateway ${HOST_GATEWAY}

Over!

基于 Nginx 的网关级 HTTP 透明代理

出于某些需求在网关级架设 HTTP 透明代理,劫持用户 HTTP 请求,转发或直接进行响应。

iptables 配置
iptables 用于将经过网关的 TCP 80 端口的上行流量转发至网关上的 Nginx 服务。

sudo iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j DNAT \
--to-destination 网关IP:端口

Nginx 演示配置

worker_processes  1;
 
events {
    worker_connections  1024;
}
 
http {
    include       mime.types;
    default_type  application/octet-stream;
 
    sendfile        on;
    keepalive_timeout  65;
 
    server {
        listen       8000;
        server_name  localhost;
 
        resolver 8.8.8.8;
 
        location /test {
            proxy_pass http://hev.cc/sftp/files/;
            proxy_buffers 256 4k;
            proxy_max_temp_file_size 0k;
        }
 
        location / {
            # 包含关键词 '计算机' 重定向至 /test
            rewrite ^.*计算机.*$ /test last;
 
            # 通用透明代理
            proxy_pass $scheme://$host$request_uri;
            proxy_set_header Host $http_host;
            proxy_buffers 256 4k;
            proxy_max_temp_file_size 0k;
        }
    }
 
    # 匹配 *.baidu.com 域名
    server {
        listen       8000;
        server_name  *.baidu.com;
 
        location / {
            root   html;
            index  index.html index.htm;
        }
    }
}

Over!

重新实现了 Socsk5

可能你会想实现那么多的 Socsk5 能吃吗?其实我只是想研究一下 I/O 模型,拿它来练习一下,如果效果不错也可以拿来用用。本次的实现没有使用 GLib,或许我真的想再也不用 GLib 啦?应该是这样的吧,至少我已经开始在实现我需要的东西。HevLib 就是我的一个初级替代品吧,目前仅仅包含最基本的数据结构、EventSource、EventLoop 等等。更多的数据结构与算法还有类型和对象系统就在以后有需要的时候再实现,一步一步来吧。

重写的 Socks5 Proxy 就是使用了 HevLib 的事件循环机制(Epoll,优先级排序),目前是单线程异步事件驱动的,感觉异步事件驱动实现起来还是有点麻烦的,和内核的进程调度一样,要上下文切换,实际来说 Session 中已经存储了上下文了,要做说也就是流程控制,我是简单的使用了一个状态变量控制的(可能不是太好,有好的方法可以告诉我哦)。

另外,在 DNS 解析上遇到一点麻烦、gethostbyname 虽然工作的没问题,显然这个阻塞的方法并不适合我现在的模型,又看了一下 getaddrinfo_a 和 c-ares 这个异步 DNS 查询库,结果发现想套到当前的事件循环机制中都有一些麻烦。后来就直接基于 UDP 实现了一个简单的异步的标准A记录查询器,简单又好用。

现在服务已经在 VPS 上部署了,RAM 的使用由原来的 300+M 直接下降到 80+M,功能还和原来一样的。;)

代码仓库:https://github.com/heiher/hev-socks5-proxy

Over!

在 iOS 上使用 Socks5 代理

创建 PAC 脚本

function FindProxyForURL(url, host)
{
    if (isInNet(host, "192.168.1.0", "255.255.255.0"))
      return "DIRECT";
    return "SOCKS xxx.xxx.xxx.xxx:xxxx";
}

将此脚本放入一个 Web Server 的服务目录中。

应用代理服务
1. 打开设置 -> Wifi -> 选择当前使用的 Wifi。
2. 将 HTTP 代理置于 Auto 模式,输入上面文件的 URL。

Over!

SSH using a SOCKS or HTTP proxy

If you follow planet debian, you may already know about the ProxyCommand directive in $HOME/.ssh/config. It allows OpenSSH to connect to a remote host through a given command.

One setup that I use a lot is to have connections be established through a SOCKS proxy. Until today, I was using connect, a small tool written by Shun-ichi Gotô. The typical setup I used is:

    Host *.mydomain.com
    ProxyCommand connect -S socksserver:1080 %h %p

I also use jump hosts occasionally, with a setup like this:

    Host somehost.mydomain.com
    ProxyCommand ssh otherhost.mydomain.com nc -w1 %h %p

And today I discovered that netcat-openbsd does support connexions through a proxy, either SOCKS or HTTP. Why keep using two different tools when you can use one? 😉 So I changed my setup to:

    Host *.mydomain.com
    ProxyCommand nc -xsocksserver:1080 -w1 %h %p

The default is to use SOCKS 5, add -X4 for SOCKS 4 and -Xconnect for HTTP CONNECT proxies. Note that it doesn’t support choosing which end does the name resolutions like connect does with the -R option.

From: http://glandium.org/blog/?p=223

Over!

修复 ModemManager 中华为 CDMA 设备的信号获取

在 ModemManager 0.6 及之前版本中,华为 CDMA 设备的信号获取依赖于 MMGenericCdma 基类实现的 MMModemCdma 接口的 get_signal_quality 方法。在此方法的实现中通过 AT+CSQ 或 AT+CSQ? 查询设备的 CDMA 1X 信号强度。但是华为的设备返回的 +CSQ 数据格式与代码中的格式并不相符,导致返回的信号数据并不能使用,换言之什么也没做,NetworkManager 看到的就是无信号!

目前 CDMA 设备是有两类信号要获取的,分别是 CDMA 1X 和 EVDO,而当前的 org.freedesktop.ModemManager.Modem.Cdma D-Bus 接口中只有一个方法 GetSignalQuality 且只能返回一个信号值。

在插件中的 MMModemHuaweiCdma 子类里实现了对非主动上报的 CDMA 1X (^RSSILVL) 和 EVDO (^HRSSILVL) 信号进行了更新,也仅此一处涉及到了 EVDO 信号的获取。

基于上述的情况,产生了这样的一种修复方案:在 MMModemHuaweiCdma 中重新实现 MMModemCdma 接口类的 get_signal_quality 方法。在此方法中根据当前的 CDMA 1X 和 EVDO 网络注册情况获取信号,当 EVDO 注册状态为 Unknown 时通过 AT^CSQLVL 获取 CDMA 1X 信号并更新,而当 EVDO 注册状态为非 Unknown 时通过 AT^HDRCSQLVL 获取 EVDO 信号并更新。

https://github.com/heiher/ModemManager/commit/4711bfc79abafd04d678c4c95976e9e7d561d2c4

在基类 MMGenericCdma 中信号变更还会触发信号 org.freedesktop.ModemManager.Modem.Cdma.SignalQuality,与上述规则相同,当 EVDO 注册时只返回 EVDO,反之返回 CDMA 1X。

https://github.com/heiher/ModemManager/commit/2a13ed070c2762058b4150c7069967df1bd4e6de

Over!

组播技术中IPv4地址到MAC地址的映射

以太网组播MAC地址

以太网传输单播IP报文的时候,目的MAC地址使用的是接收者的MAC地址。但是在传输组播数据包时,其目的地不再是一个具体的接收者,而是一个成员不确定的组,所以要使用组播MAC地址。

IPv4组播MAC地址
IANA规定,IPv4组播MAC地址的高24位为0x01005E,第25位为0,低23位为IPv4组播地址的低23位。IPv4组播地址与MAC地址的映射关系如图1-6所示。

图1-6 IPv4组播地址与MAC地址的映射关系

由于IPv4组播地址的高4位是1110,代表组播标识,而低28位中只有23位被映射到IPv4组播MAC地址,这样IPv4组播地址中就有5位信息丢失。于是,就有32个IPv4组播地址映射到了同一个IPv4组播MAC地址上,因此在二层处理过程中,设备可能要接收一些本IPv4组播组以外的组播数据,而这些多余的组播数据就需要设备的上层进行过滤了。

Over!

From: http://0bill0.blog.51cto.com/195306/300481