OpenWrt无线Wifi客户端模式

前言

前一篇讲到了OpenWrt的网络结构,这一篇讲讲OpenWrt的Wifi客户端模式,这主要是满足那些懒得接网线的人:)。

Wifi一般用的是AP(Access Point)模式:无线路由器作为一个Wifi热点为其他的Wifi客户端提供连接服务。

这里要用到的是Wifi的STA(Station)模式:作为客户端连接AP模式下的Wifi,这个一般笔记本的无线网卡都是这种模式(详细的Linux下支持的Wifi模式看这里),网络结构图:

上图中左边STA客户端模式下的无线网卡作为WAN把192.168.2.0/24划为内网,用NAT方式连接外网的Wifi AP节点(192.168.1.1)。这个很像经典的OpenWrt WAN和LAN网络结构,只不过把WAN的以太网接口换成了Wifi。

OpenWrt设置

在OpenWrt下主要是设置/etc/config/network、/etc/config/wireless这两个文件,其他的都与默认的LAN和WAN模式相同。

/etc/config/network下,关闭VLAN(enable_valn=0),lan接口设置成静态并去掉网桥(默认为’option type bridge’,Wifi通常自动桥接到lan接口),wan去掉’option ifname ‘选项(无线Wifi接口会自动加入wan作为ifname)。

config switch eth1
    option reset 0
    option enable_vlan 0

config interface loopback
    option ifname lo
    option proto static
    option ipaddr 127.0.0.1
    option netmask 255.0.0.0

config interface lan
    option ifname eth1
    option proto static
    option ipaddr 192.168.2.1
    option netmask 255.255.255.0

config interface wan
    option proto dhcp  

配置以后所有交换机上的接口都变为内部LAN,而无线Wifi作为WAN连接外网。LAN和WAN之间用NAT方式进行地址转换(具体在firewall的WAN设置masq=1,默认已经设置好了),firewall的NAT选项叫Masquerade(伪装),就是WAN接口把内网的数据包源地址伪装成自己的,很形象:)。

我一开始连接失败用Tcpdump查看wlan0,发现数据包还没有NAT伪装,最后发现是firewall没启动,所以确保firewall开机启动:

/etc/init.d/firewall enable

查看firewall是否启动:

/etc/init.d/firewall enabled && echo on

/etc/config/wireless下,设置Wifi参数:

config wifi-device radio0
    option type mac80211
    option channel 0
    option hwmode 11g
    option txpower 0

config wifi-iface
    option device     radio0
    option network    wan
    option mode       sta
    option ssid       yourAPssid
    option encryption psk2
    option key        yourkey

主要是设置mode为sta,network选择要自动加入wan,填上要连接Wifi AP的ssid、加密方式encryption和密钥key,全部完成后重启网络,Wifi连接成功后WLAN LED灯会亮起。

/etc/init.d/network restart

把你的台式电脑网线随便插入LAN口,这样你就成为了一台有无线网卡的台式机了,省去了用网线想方设法连接其他房间路由器的烦恼:)。

参考

http://wiki.openwrt.org/doc/howto/clientmode

http://wiki.openwrt.org/doc/recipes/routedclient#using.masquerade

OpenWrt网络结构

OpenWrt的网络配置很丰富,在我看来几乎可以完成任何网络结构。下图为一个支持OpenWrt的路由器网络结构:这个路由器内部交换机有6个口,其中1个WAN口、4个LAN口、Port5默认连接内部网卡eth0,还有连接Wifi的无线网卡接eth2,eth3保留。

从中我们可以看到这个路由器最多支持3个物理网络接口eth0、eth1、eth2。其实一般路由器有两张以太网卡和一张无线网卡,但更多的路由器里只有一张以太网卡和一张无线网卡。

最让我惊奇的是OpenWrt网络的灵活性,它主要靠VLAN和(Bridging)网桥等实现。

  • VLAN一般路由器为节约成本只有一张网卡(我的理解是以太网控制芯片),但如何接入多个网络呢?(路由器按常理至少要两张网卡吧),这就是VLAN的功劳啦。VLAN(Virtual Local Area Network)是虚拟局域网缩写,是把局域网中的同一工作组的主机连在一起,隔绝不同的子网(在一个或多个交换机上),这种局限增强了工作组间的保密性,也减少了全面广播的副作用。用了VLAN也就把连接子网用的路由器给省了,省钱而且效率还很高。

    VLAN需要路由器内置的交换机支持(一般都支持啦),最多可以划分4096个VLAN。一般使用只划分两个VLAN:WAN和LAN,分别对应外网和内网。如果是纯粹的VLAN,则WAN和LAN之间是隔离的,互相不能通信,但在自己的VLAN里可以自由通信。

  • Trunking用一张网卡怎么连接两个网络呢?不知你是否留意到上图中的Port5,Port5一边连接路由器,一边连接网卡eth0,它的作用就是连接vlan0和vlan1。这就是采用VLAN的Trunking技术,在Trunk Port(port5)经过的以太网帧上打标签(Tagging)用以区分来自那个VLAN,然后路由器用网卡eth0接收并处理标签从而处理(在CPU中处理),这就是所谓的单臂路由器,很形象啊:)。
  • Bridging网桥说穿了就是交换机,它就是用软件模拟以太网交换机,连接多个以太网网卡(虚拟的或物理的)分享同一个IP子网。在OpenWrt中,网桥主要用来连接无线WIFI网络和LAN,组成一个统一的内部局域网

最后为了方便理解,我画了一张示意图用普通的交换机和路由器解释上面提到的VLAN、Trunking和Bridging:

hand

参考

VLAN动画详解

OpenWrt network interface

Linux下的网桥

虚拟机安装OpenWrt X86(硬盘镜像img文件)

前言

最近手痒又开始玩OpenWrt,干脆在虚拟机上装了一个。在虚拟机上装OpenWrt有很多方法,官方网站甚至给出了WMware的虚拟机的硬盘文件,我选择原始的硬盘镜像img文件入手,感觉还是很方便的。

准备

  1. 虚拟机我用的是免费的WMware Player,基本够用了,注意要注册后下载。
  2. Linux发布版LiveCD这个有很多选择,比如Ubuntu的LiveCD等。我这里用的是比较小巧的基于Ubuntu的Lucid Puppy,整个LiveCD才100多M。这个主要用作启动盘,方便烧写OpenWrt镜像文件到虚拟机硬盘。
  3. OpenWrt X86硬盘镜像文件这个直接从官网上下载,解压后得到img文件就是要安装的硬盘镜像文件。
  4. 一个U盘这个主要用来给虚拟机拷贝OpenWrt X86的硬盘镜像文件的。

开始

首先新建个空的Linux虚拟机,硬盘大小为100M左右(OpenWrt的硬盘镜像才50多M,够用了),注意要保留USB接口。

WMware 设置
在虚拟机CDROM上设置ISO镜像文件为Puppy Linux的iso文件,然后启动虚拟机进入Puppy Linux界面。

Puppy Linux
在Windows上用U盘拷贝OpenWrt X86硬盘镜像文件(openwrt-x86-generic-combined-ext2.img),然后拔下U盘。

为了能在虚拟机Puppy Linux中识别U盘,接下来要先点鼠标进入虚拟机里面,再插上U盘,这样WMware才能检测到是虚拟机需要U盘而不会被外边的Windows抢走U盘:)。

最重要的一步来到了,从U盘把OpenWrt的镜像文件拷贝到系统根目录(root)后,开始真正的安装了。其实安装就一条命令:

dd if=openwrt-x86-generic-combined-ext2.img of=/dev/sda

用来强大的dd命令直接拷贝镜像文件覆盖硬盘,因为img文件原本对应一个硬盘的镜像嘛。因为OpenWrt本身的硬盘空间只有50多M,空余的硬盘空间也就无所谓了。

最后重启虚拟机,选择从硬盘启动后OpenWrt也就装好了:

Openwrt

Hash算法的碰撞概率

Hash算法的用途

  • 产生全局唯一标识 尽管不可能,不过小范围内可行,下面会讨论。
  • 校验和(Checksum) 其实Checksum和Hash还是有区别的,看这里
  • 密码安全 一般主要用来做密码的签名,例如在数据库里存放MD5后的密码。如果要保证密码的安全,防止被彩虹表攻击,可以加盐(Salt)
  • Hash表索引 这个应该最常用的。

Hash算法随用途的不同而不同,例如校验和(Checksum)Hash算法需要尽量高效、快速(如CRC),而在密码安全是则必须低效、缓慢从而避免被暴力破解(如MD5、SHA-1等)。

理想中的Hash算法的一个共同特点那就是产生的值是随机和唯一的,但根据鸽子窝原理(pigeonhole principle)这是不可能的,但是碰撞发生的概率大体是怎么分别的呢?

生日悖论

这个Hash的碰撞问题其实与生日悖论(Birthday problem)一样:

    如果一个班级上有30个同学,则至少出现两个人同生日的概率是多少?(假设不考虑闰年,一年365天)

归纳一下问题变成:

    假设从集合m中取n个(n > 0, n <= m),则取出相同的概率是多少?

用高中的组合数学得到公式如下:

公式1

因为k/m远远小于1(k为30,m为365),可以用泰勒级数的一级近似表示

公式2

公式3

最后得到结果:

公式4

这样可以算出生日悖论里的概率来:

    30个人中有同生日的概率P(30) = 70%
    70个人中有同生日的概率P(70) = 99% (这个足够让人惊讶了,这就是为什么叫悖论的原因了:))

概率的分布图:

Hash算法的碰撞概率

假设Hash算法是随机的,根据以前的公式得到碰撞的概率P(m,n),m代表Hash产生的个数(一般为2^n,MD5为128位,所以为2^128),n为连续Hash的次数,当n值远小于M时用泰勒级数一级近似得到简化的公式:

P(m,n) = 公式5

Hash多少次以后碰撞的概率为50%呢?也就是根据概率和m求出n:

N(p, m) = 公式6

    16位Hash碰撞概率为50%,则n = 301次
    32位Hash碰撞概率为50%,则n = 77162次
    128位MD5碰撞概率为50%,则n = 21,719,381,355,163,562,492次

参考

http://en.wikipedia.org/wiki/Birthday_paradox

http://www.codinghorror.com/blog/2007/12/hashtables-pigeonholes-and-birthdays.html

http://www.codinghorror.com/blog/2012/04/speed-hashing.html

http://www.skrenta.com/2007/08/md5_tutorial.html