Linux中的抓包与截包(一)

前言

俺作为一名搞网络的民工,总有一颗瞎折腾的心。

近日,被要求调研一下OVS这个宣称运行在内核态的数据包交换程序。既然是数据包交换程序,必然涉及到数据包截取层面,关于OVS的数据截取策略,俺百思不得其解。近日,俺在追代码追出些眉目,特此分享,顺便,总结下的Linux内部数据包抓取的方法及思路。

几种模型

根据俺的经验,Linux内部的数据包抓取的模式大概可以用以下几种方法或软件予以概括。

  • ovs/bridge
  • libpcap
  • openvpn
  • netfilter hook
  • proxychains/proxifler

ovs/bridge必须要求加载一个kernel module,以驱动的形式进入内核,从内核的层面截取数据包。libpcap主要使用了kernel的socket接口,使得数据包能直接复制到用户空间。openvpn使用了tun/tap驱动,直接创建一个虚拟的网络设备,并复制该网络设备的数据包直接到应用层。netfilter hook则使用netfilter框架,在内核的几个hook点注入抓包代码。

OVS/Bridge

Open vSwitch is a production quality, multilayer virtual switch licensed under the open source Apache 2.0 license. 
OVS简单来说,就是交换逻辑跑在内核态,控制逻辑跑在用户态,中间用netlink进行通信的交换机程序。 换句话说,OVS其实就是一种具有灵活转发逻辑的linux bridge设备。

OVS目前已经在3.3版本中merge进入内核。以下的所有分析基于内核4.3版本,具体源码可以通过LXR查看。

OVS如何维护所谓的flow等等逻辑就不再细说了,软件工程那一套直接往上堆就可以了。不过可能必须注意的是内核里面加锁的逻辑,否则kernel panic可不是闹着玩的。

OVS这里截取数据包的逻辑可以直接定位到net/openvswitch/vport-netdev.c文件中的ovs_netdev_link函数。该函数会在应用程代码执行ovs-vsctl add-port br0 eth0后经过netlink被调用。该函数中里面关键的一句话为112行 
err = netdev_rx_handler_register(vport->dev, netdev_frame_hook,113 vport);
继续追该函数进入/net/core/dev.c的3718行,该函数的注释为
Register a receive handler for a device. This handler will then be called from __netif_receive_skb. A negative errno code is returned on a failure. For a general description of rx_handler, see enum rx_handler_result.
大概意思为,该函数为该设备注册一个数据包接受的处理函数rx_handler,该处理函数在__netif_receive_skb中被调用, __netif_receive_skb在根据rx_handler的返回值 rx_handler_result决定后续处理。

继续跟一下rx_handler_result看看如何,定位到include/linux/netdevice.h中看到这个枚举类型有如下多个值,其中RX_HANDLER_CONSUMED最为重要。
If the rx_handler consumed to skb in some way, it should return RX_HANDLER_CONSUMED. This is appropriate when the rx_handler arranged for the skb to be delivered in some other ways. 
这个CONSUMED顾名思义,就是这个包,已经被我处理了,接下来就不用走TCP/IP协议栈了。而OVS的代码中,也使用了这个值。

继续跟到OVS所用来钩住内核的rx_handler函数
static rx_handler_result_t netdev_frame_hook(struct sk_buff **pskb)
{
struct sk_buff *skb = *pskb;
if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
return RX_HANDLER_PASS;
netdev_port_receive(skb);
return RX_HANDLER_CONSUMED;
}
喏,net_port_receive后,返回了RX_HANDLER_CONSUMED,告诉了内核,OK,这个包我OVS处理了,别往上递交了。net_port_receive函数是OVS内部的逻辑了,即什么流表那一堆东西,这些软件工程的东西就不再分析了。

那么OVS的分析到这里为止,OVS这种模式使用了内核模块,并且使用了net_devicenetdev_rx_handler_register函数作为截取数据包的手段,值得学习。

同样的,大家可以分析linux bridge的源码,采用了同样的手段来截取数据包。


libpcap

libpcap is a system-independent interface for user-level packet capture. libpcap provides a portable framework for low-level network monitoring. 
似乎上面的引用没啥用,好吧,tcpdump和wireshark底层都是这货在抓包。 这货其实还蛮有用的吧?

以下的代码分析,基于libpcap1.7.4。打开网络设备逻辑直接定位到Pcap-linux.c文件的activate_new函数,该函数的注释写的很明白呀。
/*
 * Try to open a packet socket using the new kernel PF_PACKET interface.
 * Returns 1 on success, 0 on an error that means the new interface isn't
 * present (so the old SOCK_PACKET interface should be tried), and a
 * PCAP_ERROR_ value on an error that means that the old mechanism won't
 * work either (so it shouldn't be tried).
 */
大概意思是:我们用了新版kernel的PF_PACKET接口来实现这个东西,但是,考虑到兼容性,我们会在老的版本SOCK_PACKET尝试下是否可以使用。这个SOCK_PACKET是个历史遗留问题了,得追溯到2.0内核去了,因此,就不做多考虑了。

该函数中首先处理一大堆历史遗留问题。定位到3162行,直接用SOCKET_RAW打开socket接口。

/*
* Open a socket with protocol family packet. If the
* "any" device was specified, we open a SOCK_DGRAM
* socket for the cooked interface, otherwise we first
* try a SOCK_RAW socket for the raw interface.
*/
sock_fd = is_any_device ?
socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)) :
socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 
注意到,处理了下any这种设备类型,使用SOCK_DGRAM来打开接口。

关于读取数据包的逻辑定位到1544行pcap_read_packet
注释依旧明白
/*
 *  Read a packet from the socket calling the handler provided by
 *  the user. Returns the number of packets received or -1 if an
 *  error occured.
 */
实在不想分析了,一大堆的宏定义,简单地说吧,直接从pcap_t里面读取数据包,然后做过滤,最终调用回调函数即可。

实际上比较简单,libpcap为了兼容性写了太多的代码,导致看起来蛮麻烦的。
简单来说,内核接口PF_PACKET协议族的SOCK_RAW实现。

参考文献:

OVS部分

http://laoar.net/blog/2015/04/27/open-vswitch/

Libpap部分

Exploit XJTU_WLAN(二)

前言

俺在前文中剖析了XJTU_WLAN这个WiFi的一些漏洞。本文接着前文,进一步优化,实现对所有流量的转发,而非单端口的代理。本文旨在实战,俺也不再浪费笔墨来讲述TAP/TUN驱动的原理。

炊具一览

Rasbery Pi一枚(自购无线网卡)
ShadowVPN一枚
202.117.0.0/18或者115.154.0.0/16的主机一枚

菜谱分析

解决方案如下图所示,Raspberry Pi上面有两张物理网卡,分别是eth0(Pi自带)和wlan0(自购)。
需要上网的设备为左边的My Mac,其中蓝色的块为数据包,首先数据包由My Mac发送到tun0上,tun0再将该数据包打上紫色的UDP53头,通过wlan0将数据送出。wlan0连接到XJTU_WLAN热点,该热点对UDP53的流量不阻拦,正确的将该数据包送向俺们安放在外面的主机,俺们的主机拆包,并将该数据送向Internet,反向流量同理。如此,便完成了一记完美的Bypass。

开始做菜XJTU_WLAN

Raspberry Pi 过水

首先Rasberry Pi上配置Shadowvpn一枚,编译后进行配置,如果默认情况下,编辑/etc/shadownvpn/client.conf文件,特别注意一下server=x.x.x.x和port=53配置。其他按需求配置即可。

配置/etc/shadownvpn/client_up.sh文件,请特别注意注释掉所有iptables与route相关的配置,否则会造成严重后果。因为shadownvpn会在进程启动后直接调用该脚本进行iptables与route的配置,由于特殊的网络环境限制,俺们需要手动的修改iptables与route配置。

 202.117.16.x过油

直接默认的方式安装shadowvpn就好了,自行配置/etc/shadowvpn/server.conf的server与port字段,使其和raspberry pi和client.conf字段一致。

实际上,注意到,shadownvpn的作者在iptables的nat配置时,显得非常暴力。更准确的写法应该是source字段写为客户端的ip地址就可以了。但是实际上,由于配置服务端时并不知晓客户端的IP地址,所以作者在这里采取了折衷的做法。
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  anywhere             anywhere             /* eth0 (shadowvpn) */

Pi与Host一锅闷 

经过上述的过程,想必大家对shadowvpn这个小程序已经有所了解,其实shadownvpn利用了kernel 2.2.x的tun/tap特性,俺这边文章还是以实战为主,便不再对该特性做深入的解释。

配置俺的Mac电脑的IP地址与网关,注意到网关为Pi的IP地址。其他按照喜好添加。

登陆202.117.x.x的主机,开启shadownvpn -c /etc/shadownvpn/server.conf,注意更改iptables的规则udp 53接受,俺之前就因为这个原因,导致装逼失败。

配置好pi的eth0的IP地址,利用SSH登陆,首先iwconfig wlan0 "XJTU_WLAN",使得wlan0接口连接XJTU_WLAN热点,然后dhcpclient wlan0,获取IP地址等信息。如果此时DNS已经能够顺利解析,其实你已经成功了一大半。继续,直接执行shadownvpn -c /etc/shadowvpn/client.conf,开启shadownvpn客户端进程,现在注意到ifconfig之中出现了tun0接口,并且ip为10.7.0.2,接着ping 10.7.0.1,试试看是否已经成功搭上梯子。

接着,配置路由规则与NAT。首先ip route del default删去默认的转发规则,加上ip route add default via 10.7.0.1,接着加上通向目的主机的规则,ip route add 202.117.x.x via 49.208.0.1。OK,搞完这两步,应该你的Pi能够正常上网了,试试百度能否打得开(哎,百度在俺心中沦为了,逃。。。)

最后一步,开启NAT,使得接入小Pi的主机也能正常浏览网页,iptables -t nat -A POSTROUTING -s 192.168.x.x -j MASQURADE -o tun0,打完收工。

试试你的小电脑能够乖乖的上网了?

总结

好了,俺记得有同僚问我,难道你交网络中心的人吃素的?俺的回答:当然不是。好吧,为了封堵这个东西,去换掉所有天花板上的AP,你说划算不划算?

当然,俺如写流水账般洋洋洒洒才手写了这么几行,实际上,在本文背后的技术细节还是蛮多的,譬如TUN/TAP,Netfilter模块等,都不是看了本文就能了解的,特别是netfilter的链/表的运行机制与iptables的配置,其实俺还是弄了好久才搞懂咧!

谢谢观看!

由MAC地址谈到网卡驱动

近日,有个需求是,通过u-boot进行PXE启动,采用的硬件为Xilinx的Zedboard.

再这里,碰到个严重的问题,mac地址冲突。对于绝大多数的嵌入式系统而言,其mac地址冲突是个经常发生的问题。如果mac地址冲突,则会造成2层交换机的工作不正常。表现在外面的现象则是,两台冲突机器同时ping包,同时,只有一台机器能够正常通信。

这种不正常现象是做高层开发的难以遇见的情况。本文就不再分析mac地址冲突对网络造成的影响,因为不同的硬件交换机对mac地址冲突所采取的处理方式不同。

OK,返回正题,让俺们深入mac地址,谈谈内核及uboot中的内核驱动。

首先,提一个问题,mac地址是否可以修改?绝大多数以教科书为范本的“学霸”的答案是“不可以”,不少喜欢折腾的同学的答案是“可以”。但是俺的答案是“不一定可以”。

为什么不可以,则要从ifconfig这个程序说起。大家可以轻松地找到如何修改MAC地址。

sudo ifconfig eth0 hw ether 08:00:00:00:00:01

那么问题来了,这个指令到底深入到内核去,它干了啥?深入到内核,则必然联系到驱动这个层面,当然在Unix/Linux世界里面,通常是module来替代。

一个不干活的驱动

首先,俺们来看一个简单的rt8139的驱动
其实准确地说,下面根本就不是驱动代码。

如上的代码可以通过cc -I/usr/src/linux-2.4/include/ -Wall -c rtl8139.c的指令编译后,通过insmod进入内核,便能够通过ifconfig -a看到该设备。当然,代码太古老,以至于现在难以编译通过。不过通过如上的代码可以看到网络驱动的大概。

关注46行,
register_netdev
将 rtl8139 注册为网络设备,如果成功,则网络设备就注册成功了,这时,利用ifconfig就能看到rtl8139这个设备了。

关注40行,就能找到这个设备。40行init里面赋,值为rtl8139_init函数,该函数接受一个net_device作为参数,

关注41行,注意到驱动编写者需要做的,直接利用内核传入的net_device勾住初始化代码。将net_device结构内的open,stop,hard_start_xmit函数hook在rtl8139_open,rtl8139_release,rtl8139_xmit上面。

其中open/rtl8139_open函数会在用户调用ifconfig rtl8139 up时被调用。stop/rtl8139_release会在用户调用ifconfig rtl8139 down时调用。而hard_start_xmit/rtl8139_xmit会在协议栈向驱动注入数据时,请求发送时使用,例如socket接口中的write函数。

当然,上面的代码实际上并非rtl8139的驱动的代码,因为实际上,所有的hook的函数,实际上除了打印一些信息以外什么也没干。

看完以上,诸位似乎已经大体地了解到什么是一个网卡驱动程序了。不过现实的网卡驱动程序可没有这么简单。首先,聪明的读者似乎已经注意到,俺的网卡驱动里面似乎并没有涉及到数据的接收过程,其次,俺的网卡驱动里面也没有任何的MAC地址的配置信息。

解剖Realtek 8139驱动

接下来,俺利用Kernel 4.3的Realtek 8139的驱动程序8139too.c来讲解MAC地址与驱动的关系。代码由于过长,就不再贴出来,可以自行点击上方的超链接下载。(注:所有的代码行均缘于8139too.c文件,本文限于篇幅,只粘贴重要代码及其函数)

烦人的MAC地址

关注2238行开始的函数rtl8139_set_mac_address,该函数接受两个参数,第一个参数是net_device结构体,用以描述该网络设备,第二个参数是个空指针,用于传送用户空间传来的MAC地址值。
可以看到验证完以太网地址后,直接利用
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
将用户的值设置进入net_device对象的dev_addr内部,这一步就直接告诉内核,用户想要改变网卡设备的地址。

在配置完内核维护的网络设备的地址后,立即看到一把spinlock加锁,然后利用各种宏开始写寄存器。之后进行锁的释放。

实际上,写寄存器的主要目的在于使物理的MAC芯片能够过滤非本机的数据包,而不在于发送数据包的校验。

因此,在解析完此段代码后,俺想大部分读者已经能理解,为什么俺在文章开始的时候提到了MAC地址不一定可以被修改的原因。简单地说,如果驱动程序直接就return了,实际上是达不到修改MAC地址的功能的。

那么肯定会有读者会问,既然MAC地址能够被写入,那俺们教科书上所谓的与网卡绑定的MAC地址又是在哪里呢?

这个问题的答案在rtl8139_init_one函数中1004-1007行。循环内部不断地写入dev->dev_addr这个变量,而这个变量正是内核用以保存MAC地址的数据结构。

解锁收包逻辑

接下来,俺们来了解下数据接收的功能。即网卡驱动怎么拿数据,再怎么将数据递交个上层。这一块由于linux内核的NAPI使得问题分析变得复杂。

让俺们定位到1333行,rtl8139_open中,调用了request_irq,注册中断处理函数。
retval = request_irq(irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev);
将中断的函数的第二个参数为rtl8139_interrupt,即中断处理函数。

继续追踪rtl8139_interrupt函数,2197-2202行。

这几行核心代码用于收取数据包。其中8139的驱动中,直接调用__napi_schedule函数进行处理。而这个__napi_schedule函数所做的,就是将将本数据包的处理交给NAPI系统。等待NAPI系统进行统一调度。具体的细节可直接看考Linux Foudation的关于NAPI的这篇文章

总之上,等待调度时间到了,  NAPI会调用某个hook的poll函数,8139通过1013行的这段代码进行hook。
netif_napi_add(dev, &tp->napi, rtl8139_poll, 64);
那么真正的处理函数便交给了rtl8139_poll函数。

该函数中核心在于rtl8139_rx函数的调用,通过调用这个函数,直接进入最后的skb打包并递交上层的流程。

rtl8139_rx函数大部分工作是从从环形队列中取出数据包,并打包上传。
定位到rtl8139_rx的2038-2067行。就能找到最重要的两个调用:
skb->protocol = eth_type_trans (skb, dev);
netif_receive_skb (skb);
分别解析数据包,并调用上层IP或ARP逻辑。
至此,驱动所有工作就完成了。接下来正式进入TCP/IP协议栈进行处理。这里就不在本文的涉及范围。

总结:
俺在分析网卡驱动逻辑的时候,被NAPI系统给折腾得不轻,目前的Linux已经不像是书本的设计了,本来interrupt函数中可以直接进行skb打包,但是NAPI的介入,使得调用逻辑不再连贯。而绝大多数的针对于网卡驱动的分析是建立在旧驱动的基础上。因此,俺写了本篇文章,希望大家避免走弯路。

最后,贴出我所参考的4.3内核中的源代码文件8139too.c,留以备份。
谢谢观看。


错误处理最佳实践

该帖子内容源于互连网的翻译,归纳与整理。

1. 尽量采用自定义的Exception。
        采用自定义的异常,能够为错误提供更多信息。
2. 尽早抛出异常。
        尽早抛出异常能够尽早发现程序错误。
3. 尽晚捕获异常。
        尽晚捕获异常能够使调用者发现错误。
4. 将异常记入日志系统。
5. 单个catch去处理所有异常。
        不理解。囧。
6. 尽量不使用异常
         异常系统执行通常比if判断后直接返回慢很多。
7. 利用@throws 写javadoc

From Java Exception Handling Tutorial with Examples and Best Practices


Spring之优劣

背景

     作为InterONet的负责人, 在写Global平台的代码的时候, 有意无意间发现管理对象的生命周期是件很头大的问题, 虽然Java的GC机制, 在很大程度上避免了C++的管理对象的繁琐,但是, GC机制一旦在运行GC时,程序的“假死”现象也让人头疼。
     在InterONet迭代初期,所有的对象,都是靠new语句来进行的, 因此也具有强烈的耦合, 虽然“Program to Interface”这个法则一直深入我心, 不过在实例化对象时,难免用到具体类, 因此不能完全做到纯粹的“to Interface”。
      此时,GoF一书中所提及的Factory Pattern也许就是帮助来解决这个问题的一剂良药。此时,假设有一个框架能够帮助我(1)管理对象的生命周期(2)提供工厂模式 那也就再好不过了。
      所幸,Java的reflect特性正是可以用来做到上述的工作, 不过如果让我写InterONet之余, 再写一个这个框架, 岂不是有再造轮子之嫌, 俨然不符合作为互连网业内的“潜规则”。

IoC与DI

    IoC, 洋文全称为Inversion of Control,  我们常把其称为控制反转。 第一次接触到这个term是在耗子哥的Coolshell的这篇文章中,当时还觉得云里雾里, 不过时至今日, 也算是领会到耗子哥的良苦用心。
    为什么叫做控制反转呢, 俺就来解释一下: 所谓控制, 指的是你对于其他人的控制,譬如说你的代码里面new了一个别人写的类,那么你就在控制别人的对象。 所谓反转,指的是将这种控制交出去, 交给别人(第三方)来控制。 其实这里的思想我觉得跟三权分立有相似之处。 好吧,作为一个民工, 还是“莫谈国事”为好。
     看官肯定会想,如何交给第三方来做控制呢? 打个比方就特别好理解了, 两个企业, 其中A企业是你管的,B企业是别人管的。 现在A,B企业要合作, 那么B企业肯定要来人到你们企业喽, 那你就创建一个新的职位给B企业的员工,让他过来帮你干活, 这就是传统的new对象的模式。
这个员工是你创建的, 那么肯定你要负责他的衣食住行等等。 这是何等痛苦!!! 那如何减小这种痛苦呢? 那么,我找个中介公司来帮我管理吧, 让这个中介负责这个过来的员工的衣食住行以及工资等等。这不省事, 你过来只用干活, 干完就走。这样岂不是省事许多? IoC其实就是说的这个意思, 让一个第三方来帮你做管理, 反转了你的控制。
     其实, IoC就是这种思想, 好吧,各位看官看到这里, 是不是理解了IoC呢? 那么所谓DI又是什么概念?
     继续这个例子, 你需要B企业的人来帮你干活, 那么你怎么找到这个B企业的特殊的人呢?那么这就衍生出了Dependency Injection与Dependency Lookup, DI也就是说, 你在自己的公司门口写上“招聘B企业的哪个员工”, 中介自动把员工给你送过去, 而DL就是说, 你去中介公司去查花名册, 然后中介再把人给你送来。
      因此, DI与DL其实就是两种IoC的实现方式罢了。 因为DI更为方便, 因此, 大多时候, IoC也就约等于DI了。
      注:实现方式上面,洋文的维基百科跟中文的维基百科不太一样, 不过思想是类似的,洋文的写了
      这么多,不过, 我大体看了一眼, 其实思路差不多, 只是归类形式不同罢了, 关于实现方式不是本文和核心内容,就不再多说。

Spring IoC Container

    因为俺考虑到InterONet其实更多地在于业务逻辑, 而非性能, 因此InterONet也就用Java来作为主力语言。
    Java底下有相当多的IoC容器, HiveMind、PicoContainer、Spring Framework、Apache Excalibur、Seasar 和 DPML Metro 等。 其中除了Spring俺都没有见过。
Spring Framework是一个开源的JavaJava EE全功能栈(full-stack)的应用程序框架,以Apache许可证形式发布,也有.NET平台上的移植版本。该框架基于 Expert One-on-One Java EE Design and DevelopmentISBN 0-7645-4385-7)一书中的代码,最初由Rod Johnson和Juergen Hoeller等开发。Spring Framework提供了一个简易的开发方式,这种开发方式,将避免那些可能致使底层代码变得繁杂混乱的大量的属性文件和帮助类。
    Spring的IoC Container作为整个SSH中中间层, 用来作解耦合是相当被业界推崇。 因此俺也就被其威名所吸引, 深入Spring, 了解其作用, 也为将来的工作后先预热一下。

优点

    关于优点, 俺就不再这里班门弄斧, 吹牛逼了。 直接搬运一下洋文的Wikipeida:
  • To decouple the execution of a task from implementation.
  • To focus a module on the task it is designed for.
  • To free modules from assumptions about how other systems do what they do and instead rely on contracts.
  • To prevent side effects when replacing a module.
     我就觉得第一条最重要,其他的几条感觉只要解藕了,都能推出来。

缺点

    作为一个深受马克思主义洗脑的爱国青年, 辩证主义深入我心。实际上, 主要是由于作为team leader, 必须做决策。囧。 那么废话少说了, 关于Spring有什么缺点呢?
  1. 难于调试。 毕竟依赖于别人的框架, 依赖于DI, 对于我new一个对象而言, 能追踪到对象的创建过程, 而较之于Spring而言, 这一部分是几乎无法追踪的。 因此调试上面,是肯定难于传统的方式。
  2. Spring学习曲线陡峭。对团队来说,是一次挑战。
  3. 框架重:有大约3000个类在其jar包内部,虽然其声称自己是轻量级。
  4. 需要详细的文档描述。

总结

   引用<Hamlet>一剧的经典名言: To Be or Not to Be, It is a question.

Exploit XJTU_WLAN(一)

背景介绍

     作为一名穷屌丝,用不起4G,只能靠蹭蹭学校的无线网。无奈,穷学校的无线帐号竟然只能提供给老师使用。着实让尔等屌丝伤透了心。

网页验证介绍

     OK,废话少说。渣校的XJTU_WLAN采用了网页验证方式,这个东西洋文叫做Captive Portal,首先连接进入未加密的XJTU_WLAN,接着通过DHCP客户端,请求分配IP地址,掩码,网关,DNS配置。关于这种Captive Portal不再做详细的说明,渣校的认证方式属于其中的Redirect by HTTP类型。

     这种认证方式巨大的劣势在于可以预先连接,并且获取到一个网络配置信息,这也就意味着,实际上我已经能够连入这个无线网络了。这无疑增加了我的手的机会。 再连入XJTU_WLAN,DHCP后,通过ipconfig命令,我发现我的网络配置信息如下。

IP:49.208.6.53/20
Gateway:49.208.0.1
DNS:202.117.0.20, 202.117.0.21

如何发现漏洞?

     各位看官看到如上的配置是否有有了一丝Hack的想法, 为何DNS跟本机不在一个网段,这里是否也就意味着本机可以利用DNS作为伪装与202.117.0.0/16的网内任意一台主机通信?

     笔者于是接下来就开始来验证这个答案。

$ nslookup www.baidu.com
Non-authoritative answer:
www.baidu.com    canonical name = www.a.shifen.com.
Name:    www.a.shifen.com
Address: 119.75.217.109
Name:    www.a.shifen.com
Address: 119.75.218.70

     看到如上的信息,立马就兴奋了起来。 DNS请求果真没有被拦截。好吧,DNS Tunnel肯定是毫无疑问可以去作了,利用iodine小程序即可搞定。 这个东西没有什么难度,我就不再说了。 只是因为笔者的VPS在国外,利用此种方式,实在是太慢。于是就放弃了这个想法。

     那我们继续考虑, 一般的防火墙还是没有GFVV这么这么牛逼了,不可能劫持DNS, 那么是否本机可以通过UDP53跟202.117.0.0/16任意一台机器通信?

     此处祭出神器netcat
@202.117.15.123/24 $ nc -u -l 53
@49.208.6.53      /20 $ nc -u 202.117.15.123 53

     不再贴图了,最终得到的答案是,可以进行收发包, 至此, 其实bypass XJTU_WLAN的工程已经完成了2/3。

如何绕过登录?

     随便找个udp tunnel的工具,进行一下端口转发一下,就可以了, 我用的是udptunnel(google code快关闭了,我已经将他迁移出去)。

server# ./udptunnel -s 202.117.15.123 53
client# ./udptunnel -c 127.0.0.1 3333 202.117.15.123 53 127.0.0.1 22
client# ssh -p 3333 user@127.0.0.1

     那对于小白而言,该如何操作呢?
     利用ssh不是可以打socks代理,win下利用proxifier软件,实现全局代理。linux下采用proxychains类似的工具可实现全局代理。
     本文不再详述ssh的socks代理的原理, SSH已经被用滥了,读者可自行搜索。

     在接下来的博文中,笔者会将分享如何利用虚拟网卡的方式来实现透明转发。
敬请期待!

Java多线程定时初探

此篇文章始于InterONet的多线程,因为需求中,有一个对象会定时poll另外一个对象,并且调用其方法,因此会涉及到一些定时器的问题。
output:
sleep(2000) version
 second Method
(2s...)
1230
first Method
1330

wait(2000) version
second Method
first Method
110
(2s...)
13530

其实,输出结果的差异在于,线程中调用java.lang.Thread.sleep方法,与调用this.wait()方法的区别。
对于java.lang.Thread.sleep方法是一个静态方法。
一个进程中执行了这个方法,则该进程立即进入timed wating状态。
对于this.wait()方法而言,其实则是继承了Obeject.wait()方法

我们知道Java中每个类extend Object. 因此,每个类中带有wait方法。
而Java在实现的时候,每个类都会有自己的对象锁,这个锁完全地锁住了这个对象。我们在一个类方法上面加上synchronized参数,就是说,如果想要调用这个类方法,首先必须获得这个对象锁。

回到代码中,我们看到,不管是sleep版本还是wait版本,都是首先执行了second Method。因此两个线程都获得了这个对象锁。然而,sleep的版本直接停了2秒再调用了first Method,而wait版本直接调用了firstMethod。因此,可以看出,调用wait()时,该线程释放了这个对象锁,而sleep()则没有释放这个对象锁。

贵系的UDP Flood

     始于贵校贵系网络常年遭受的UDP Flood。本以为此等问题很简单,可是数年来,竟无一人问津,网络中心也无法维护,贵系也没有一个人出面来解决下,无奈一下,怀着自己动手,丰衣足食的思想,俺开始了一个码农拯救世界的宏伟征途。233

UDP Flood分析

     经过可靠的推断,目前存在一台恶意机器接入楼层交换机,通过发送伪造ip-dst为本网段的IP,伪造MAC地址的方式发送flood攻击,此种攻击方式主要是利用了交换机固有弱点,故很难防御。因为MAC地址为伪造的MAC地址,因此,当如图所示的蓝色数据包到达交换机,发现没有这个MAC地址没有与之对应的转发端口,便直接向除源端口每个端口广播该数据包,直接造成流量被N倍放大,造成背板带宽直接crash。



解决方案:

     在没有交换机管理权限的情况下,做此等防御可谓难上加难,不过,通过伪造mac地址来欺骗交换机的方式倒是可以投机取巧一把。
     因为交换机没有一个MAC地址与原始攻击流量的MAC地址相对应,因此,只需一台机器告诉交换机说,那个攻击流量的MAC地址在我这里,请把所有流量给我,通过如上的方法,避免了交换机的flood,从而避免了攻击流量被N倍放大。

编码:

     本文中利用scapy进行上面的操作实践。

关于SDN的思考
     如果这个东西放在SDN的环境下,解决起来就非常简单。
      1) 每个host必须设置固定的ip,mac不允许其伪造ip,mac信息。 即作port-mac-ip的一对一绑定。当然,此处可以利用SDN的强大的可编程性,让这种绑定成为动态的绑定,即借助与第三方认证机制来动态绑定。这一点,就我目前的了解,传统交换机是难以做到的。

First Journey into Deep Web

     近日,著名的Tor网络据说新部署了Meek模式网桥,利用Amazon与Azure的资源进行流量混淆,着实给俺等网虫一个福音,前几日,下载好了Tor,进行了人生中第一次深网探索。

     先去Tor官网下载最新版的软件, 本文不再赘述。如图,点击上方图片中的红框处。解压缩后,点击Start Tor Browser.exe即可进入传说中的Tor网络。

     设置界面得说一下。
     首先点击Configure做一些设置,点击Next下一步。

 此处问你有没有用代理连接Internet,如果贵司没有设置诸如HTTP代理连接Baidu.com之类的网站,那就选择No。
      此处问你你的网络服务商(ISP),例如中国电信,联通,或者教育网有没有阻挡你对于Tor网络的链接,天朝的大家直接点“Yes”即可。
      此处,我选择了meek-amazon来进行连接,笔者此处的环境应该西北片区教育网。点击Connect,即可完成设置。

     再经历了漫长的等待之后,出现了如下的界面。
         点击红框处,可进行Tor网络测试。
     可以看到我目前的IP已经进行了伪装,不再是我本机的出口IP了。
     至此,应该可以进行Tor网站的浏览。
     Tor匿名网络的URL通常都比较特殊。通常是以.onion结尾,例如http://3g2upl4pq6kufc4m.onion/等。而且,针对于DeepWeb也没有特别有效的Search Engine,因此,在DeepWeb里面还保留着以往的YellowPage形式,而其中注明的则是Hidden wiki.
     本文最后推荐一个笔者经常去的站点,皮皮书屋。此站点可以下载到相当多的关于CS的书籍,关于此站的来源不再赘述,有兴趣的读者可自行Google。