-
启动
service openvswitch start
-
创建网桥
ovs-vsctl add-br br0 ifconfig br0 up
-
显示所有网桥
ovs-vsctl show
-
删除网桥
ovs-vsctl del-br br0
-
增加端口
ovs-vsctl add-port br0 eth0
-
设置网卡为none
dhclient br0
-
用 Namespace 模拟两台虚拟机网络
p netns add network1 ip netns add network2
-
创建两个虚拟网卡并加入网桥
ovs-vsctl add-port br0 vport1 -- set interface vport1 type=internal ovs-vsctl add-port br0 vport2 -- set interface vport2 type=internal tunctl -p -t vport1 tunctl -p -t vport2
-
两个虚拟网卡接入namespace
ip link set vport1 netns network1 ip link set vport2 netns network2
-
设置虚拟网卡的IP
ip netns exec network1 ifconfig vport1 192.168.0.1/24 up ip netns exec network2 ifconfig vport2 192.168.0.2/24 up
-
两个namsespace PING
ip netns exec network1 ping 192.168.0.2 ip netns exec network2 tcpdump -i vport2
-
两个namsespace NC传输
ip netns exec network2 nc -l 1234 ip netns exec network2 tcpdump -i vport2 ip netns exec network1 nc 192.168.0.2 1234
-
显示vlan信息
ovs-appctl fdb/show br0
-
显示openflow信息
ovs-ofctl show br0
-
显示流表信息
ovs-ofctl dump-flows br0
-
显示网桥详细信息
ovs-vsctl list Bridge
-
显示端口详细信息
ovs-vsctl list Port
-
显示接口详细信息
ovs-vsctl list Interface
Running Many Containers Requires Bumping Up Inotify Limits
when we see Too many open files - failed to inotify_init
, we could either bump up the limit automatically, or tell the user.
just exec:
sysctl -w fs.file-max=64000
sysctl -w fs.inotify.max_user_instances=8192
Webtorrent Redefine CDN?
最近发现了一个开源的JS东东,webtorrent:
https://github.com/feross/webtorrent
用webRTC实现了一个浏览器端的bt客户端。
这个点子我还在几年前试过呢?当时想用socketio来做,但各种限制,当时webRTC还是个小众,没有被浏览器主流实现。
试了一下,效果还差强人意。
脑洞开一下,话说这会不会是快播们的春天来了。
严肃一点再想想,是不是CDN提供商们可以利用它分担压力,提升速度,走上人生巅峰….
留待后续观察。
有关于云计算及SDN
云计算和SDN这两个名词总是被许多人挂在嘴边,他们给人的印象就是在Qcon大会上念PPT的一拨人。
作为一个实用党,下面我企图用一问一答的形式来瞎扯一番:
Q: 我是个中小企业,用openstack好还是vCenter虚拟化好?
A: 如果你能招到一个合适的人(注意,这个概率我觉得是万分之一),你可以上openstack。
如果你有足够的M,上vCenter。
如果你什么都没有,上阿里云 (我是认真的,不要黑我)。
总之,随着网络带宽提升,我觉得中小企业自建运维越来越不划算。云化是趋势。
Q: 容器技术会颠覆现有的虚拟化技术吗?
A: 不会,容器技术只是补充,全虚拟化有自己不可替代优势。
Q: SDN会替代现在的网络设备吗?
A: 可能会替代大部分网络交换设备。但是就现在的情况来看,各种SDN解决方案的性能还没有和硬件处在同一档次上。
所以将来在大型数据中心,肯定是软硬结合和持续很长一段时间。
在很多中小云平台,大部分硬件设备已经在迁移过程中了。
Q: SDN真的比传统设备灵活吗?简单吗?方便吗?
A: 首先要看方案,和传统网络一样,不同的场景实施方案也不一样。一千个现场会有一千个云实施方案。
SDN有灵活性的优势。
SDN某种意义上说,比传统网络还要复杂。
首先,真实世界的网络就是复杂的。任何隐藏复杂性的尝试都会增加复杂性。所以SDN不能拯救世界,传统硬件设备面临的复杂问题,它也一样要面对。
SDN的优势就是灵活,并非简单。
Q: 未来从事中小企业云的部署咨询工作,有戏吗?
A: 我觉得单纯做部署顾问之类的没戏。做openstack的番茄花园有戏。
如果将来GPU虚拟化成熟的话,做打金工作室的openstack 包装发行版相当有戏。
Q: SDN领域有何机会?
A: 也许SDN领域将来不会再孕育思科华为那样的大玩家,但是一定会有许多独角兽出来。
目前看到的看准一个痛点,比如苏州盛科那样,软硬结合,做芯片,交换机白牌供应商,很有机会。
或者瞅准市场空白,比如说做性能比较低的软tap,我觉得很有戏。
Is Craig Wright Real Satoshi Nakamoto?
Craig Wright 又在声明他是”中本聪”了.
“中本聪”给出的签名是:
MEUCIQDBKn1Uly8m0UyzETObUSL4wYdBfd4ejvtoQfVcNCIK4AIgZmMsXNQWHvo6KDd2Tu6euEl13VTC3ihl6XUlhcU+fM4=
我们先对信息串进行base64解码,再转换成hex是:
3045022100c12a7d54972f26d14cb311339b5122f8c187417dde1e8efb6841f55c34220ae0022066632c5cd4161efa3a2837764eee9eb84975dd54c2de2865e9752585c53e7cce
很遗憾,我们可以在交易ID:
828ef3b079f9c23829c56fe86e85b4a69d9e06e5b54ea597eef5fb3ffef509fe
中找出这个签名。可通过:
https://blockchain.info/tx/828ef3b079f9c23829c56fe86e85b4a69d9e06e5b54ea597eef5fb3ffef509fe?format=hex
找到十六进制串的交易内容
然后搜索一下hex样子的签名,遗憾地发现,能在这个交易中找到这个签名。
但是令人疑惑的是GAVIN ANDRESEN为这位”中本聪”背书:
http://gavinandresen.ninja/satoshi
Gavin不是一个无的放矢的人,他肯定是见到了更多的证据.
但是Craig Wright 又不对其他给定的文本签名来证明自己是中本聪,反而老是用这种神神遭遭的签名来忽悠大家……
卫平布莱恩特老师说,这球有意思啊…….
最后, 如果Craig Wright这个人是为了某种目的假冒的话,只能说他真是煞费苦心啊. 我不认为一个签名造假如此low的家伙能有这种能力.
但是他的一些行为如果算恶作剧的话,又未免太高段了,参考这里:
https://www.zhihu.com/question/22199390/answer/76083139
不负责任的YY一下, Craig Wright肯定和真正的中本聪有某种关系,他在bitcoin诞生之初就了解参与过.
他不是bitcoin的发明者,因为种种迹象表明,他的技术能力实在太low了.
真正的中本聪可能是他的那个朋友:David Kleiman, 但他已经死了.
呵呵, 绝佳的侦探小说体裁啊.
Git Cheat 2
整理一下经常忘记的Git命令 (版本v2)
http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html?utm_source=tool.lu
新建代码库
# 在当前目录新建一个Git代码库
git init
# 新建一个目录,将其初始化为Git代码库
git init [project-name]
# 下载一个项目和它的整个代码历史
git clone [url]
配置
Git的设置文件为.gitconfig,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置)。
# 显示当前的Git配置
git config --list
# 编辑Git配置文件
git config -e [--global]
# 设置提交代码时的用户信息
git config [--global] user.name "[name]"
git config [--global] user.email "[email address]"
增加/删除文件
# 添加指定文件到暂存区
git add [file1] [file2] ...
# 添加指定目录到暂存区,包括子目录
git add [dir]
# 添加当前目录的所有文件到暂存区
git add .
# 删除工作区文件,并且将这次删除放入暂存区
git rm [file1] [file2] ...
# 停止追踪指定文件,但该文件会保留在工作区
git rm --cached [file]
# 改名文件,并且将这个改名放入暂存区
git mv [file-original] [file-renamed]
代码提交
# 提交暂存区到仓库区
git commit -m [message]
# 提交暂存区的指定文件到仓库区
git commit [file1] [file2] ... -m [message]
# 提交工作区自上次commit之后的变化,直接到仓库区
git commit -a
# 提交时显示所有diff信息
git commit -v
# 使用一次新的commit,替代上一次提交
# 如果代码没有任何新变化,则用来改写上一次commit的提交信息
git commit --amend -m [message]
# 重做上一次commit,并包括指定文件的新变化
git commit --amend [file1] [file2] ...
分支
# 列出所有本地分支
git branch
# 克隆并在本地建立所有分支
for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do
git branch --track ${branch##*/} $branch
done
# 列出所有远程分支
git branch -r
# 列出所有本地分支和远程分支
git branch -a
# 新建一个分支,但依然停留在当前分支
git branch [branch-name]
# 新建一个分支,并切换到该分支
git checkout -b [branch]
# 新建一个分支,指向指定commit
git branch [branch] [commit]
# 新建一个分支,与指定的远程分支建立追踪关系
git branch --track [branch] [remote-branch]
# 切换到指定分支,并更新工作区
git checkout [branch-name]
# 建立追踪关系,在现有分支与指定的远程分支之间
git branch --set-upstream [branch] [remote-branch]
# 合并指定分支到当前分支
git merge [branch]
# 选择一个commit,合并进当前分支
git cherry-pick [commit]
# 删除分支
git branch -d [branch-name]
# 删除远程分支
git push origin --delete [branch-name]
# 删除不存在对应远程分支的本地分支
# 假设这样一种情况:
# 1. 我创建了本地分支b1并push到远程分支 origin/b1;
# 2. 其他人在本地使用fetch或pull创建了本地的b1分支;
# 3. 我删除了 origin/b1 远程分支;
# 4. 其他人再次执行fetch或者pull并不会删除这个他们本地的 b1 分支,运行 git branch -a 也不能看出这个branch被删除了,如何处理?
# 在fetch之后删除掉没有与远程分支对应的本地分支
git fetch -p //
# 重命名远程分支
# 在git中重命名远程分支,其实就是先删除远程分支,然后重命名本地分支,再重新提交一个远程分支
git push --delete origin devel
git branch -m devel develop
git push origin develop
# 合并branchB到branchA
# 前提是你需要的是fast-forward
# 合并本地的branchB到本地的branchA
git fetch . branchB:branchA
# 合并远端的branchB到本地的branchA
git fetch origin branchB:branchA
# 合并branch上的指定文件
# branches/A 上修改了一个文件A.h,新增了一个文件B.h,删除了一个文件C.h。
# 首先切换到master分支
git checkout master
# 不切换branch,把RemLanbranches/A上的A.h更新到当前分支
git checkout -p branches/A A.h
# 去掉-p参数,新增该B.h文件
git checkout branches/A B.h
# 删除文件目前还没找到其他办法,但效果是一样的
rm C.h
标签
# 列出所有tag
git tag
# 新建一个tag在当前commit
git tag [tag]
# 新建一个tag在指定commit
git tag [tag] [commit]
# 删除本地tag
git tag -d [tag]
# 删除远程tag
git push origin :refs/tags/[tagName]
# 查看tag信息
git show [tag]
# 提交指定tag
git push [remote] [tag]
# 提交所有tag
git push [remote] --tags
# 新建一个分支,指向某个tag
git checkout -b [branch] [tag]
查看信息
# 显示有变更的文件
git status
# 显示当前分支的版本历史
git log
# 显示commit历史,以及每次commit发生变更的文件
git log --stat
# 显示某个commit之后的所有变动,每个commit占据一行
git log [tag] HEAD --pretty=format:%s
# 显示某个commit之后的所有变动,其"提交说明"必须符合搜索条件
git log [tag] HEAD --grep feature
# 显示某个文件的版本历史,包括文件改名
git log --follow [file]
git whatchanged [file]
# 显示指定文件相关的每一次diff
git log -p [file]
# 显示指定文件是什么人在什么时间修改过
git blame [file]
# 显示暂存区和工作区的差异
git diff
# 显示暂存区和上一个commit的差异
git diff --cached [file]
# 显示工作区与当前分支最新commit之间的差异
git diff HEAD
# 显示两次提交之间的差异
git diff [first-branch]...[second-branch]
# 显示某次提交的元数据和内容变化
git show [commit]
# 显示某次提交发生变化的文件
git show --name-only [commit]
# 显示某次提交时,某个文件的内容
git show [commit]:[filename]
# 显示当前分支的最近几次提交
git reflog
远程同步
# 下载远程仓库的所有变动
$ git fetch [remote]
# 显示所有远程仓库
$ git remote -v
# 显示某个远程仓库的信息
$ git remote show [remote]
# 增加一个新的远程仓库,并命名
$ git remote add [shortname] [url]
# 取回远程仓库的变化,并与本地分支合并
$ git pull [remote] [branch]
# 上传本地指定分支到远程仓库
$ git push [remote] [branch]
# 强行推送当前分支到远程仓库,即使有冲突
$ git push [remote] --force
# 推送所有分支到远程仓库
$ git push [remote] --all
撤销
# 恢复暂存区的指定文件到工作区
git checkout [file]
# 恢复某个commit的指定文件到暂存区和工作区
git checkout [commit] [file]
# 恢复暂存区的所有文件到工作区
git checkout .
# 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变
git reset [file]
# 重置暂存区与工作区,与上一次commit保持一致
git reset --hard
# 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
git reset [commit]
# 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致
git reset --hard [commit]
# 重置当前HEAD为指定commit,但保持暂存区和工作区不变
git reset --keep [commit]
# 新建一个commit,用来撤销指定commit
# 后者的所有变化都将被前者抵消,并且应用到当前分支
git revert [commit]
remote 同步
# 查看当前远程版本库
git remote -v
#添加原始版本库
git remote add cocos2d-x git://github.com/cocos2d/cocos2d-x.git
#获取原始版本库的更新
git fetch cocos2d-x
# 合并原始版本库的代码到当前版本库中,合并前确保当前分支是master
git merge cocos2d-x/master
分支的衍合
http://git-scm.com/docs/git-rebase
diff
# 只显示两个分支间的差异,如果你想找出‘master’,‘test’的共有 父分支和'test'分支之间的差异,你用3个‘.'来取代前面的两个'.' 。
git diff master..test
# 显示你当前的索引和上次提交间的差异;这些内容在不带"-a"参数运行 "git commit"命令时就会被提交。
git diff --cached
# 显示你工作目录与上次提交时之间的所有差别,这条命令所显示的 内容都会在执行"git commit -a"命令时被提交。
git diff HEAD
# 如果你要查看当前的工作目录与另外一个分支的差别,你可以用下面的命令执行:
#这会显示你当前工作目录与另外一个叫'test'分支的差别。你也以加上路径限定符,来只 比较某一个文件或目录。
git diff test
# 显示你当前工作目录下的lib目录与上次提交之间的差别(或者更准确的 说是在当前分支)。
git diff HEAD -- ./lib
# 如果不是查看每个文件的详细差别,而是统计一下有哪些文件被改动,有多少行被改 动,就可以使用‘--stat' 参数。
git diff --stat
# 显示两次更改之间所有的文件名
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRTD HEAD HEAD^
# diff两个分支
git diff master branch/1.1 --
其他
# 生成一个可供发布的压缩包
git archive
# 临时保存/恢复现在的状态
git stash
git stash pop
# svn log -v 类似效果
git log --name-status
Migrate Centos7 From Centos6
工作环境切换到Centos7 半年有余,epel仓库里的软件版本比el6更新了不少,非常方便。
另外systemd的引入让很多程序,尤其是开机启动上,速度提升了不少。
总体来说,很多细节让你感觉很舒服,值得大家尽快切换到这个版本上了。
下面记一下从Centos6迁移到Centos7上 常见的Question:
Q: 为什么引入systemd 代替 SysV init,我就是习惯原来的 /etc/init.d/xxxx 的方法?
A: 在我看来,有两点:
-
快。 真的是快,嗖嗖的快
-
日志。 终于能取代syslog了,我对syslog素无好感,配置复杂,level巨多,还不好排障。
参考资料:
http://www.ibm.com/developerworks/cn/linux/1407_liuming_init3/
https://wiki.archlinux.org/index.php/Systemd
Q: 为什么网卡名字这么奇怪,我要原来的简单明了的办法!!!
A: 呃,好吧,我觉得虽然有一堆理由,但是网卡名字这个改变可能真的是没有产品经理的弊端。你想回到从前,很简单:
-
在 grub 加入 net.ifnames=0 and biosdevname=0 作为内核参数
-
在 /etc/sysconfig/network-scripts/ 内把你的网络卡配置文件换名为 ifcfg-ethX
-
假若你拥有多个界面并希望控制每个设备的名称,不想由内核作主,你似乎有必要通过 /etc/udev/rules.d/60-net.rules 盖过 /usr/lib/udev/rules.d/60-net.rules。
Q: grub.cfg 文件生成怎么这个奇怪,还要先配置 /etc/default/grub,再用命令生成一遍?我要直接改!!
A: 醒醒吧,我对这个改动双手赞成,至少她解决了centos6上一直被人诟病的efi问题。
Q: 嗯,我想问,ifconfig和 netstat哪里去了?
A: 额,套用官方原话回答吧:
ifconfig 及 netstat 工具程序在 CentOS 5 及 6 的应用手册内被置标为降级已接近十年,而 Redhat 决定在 CentOS 7 不会缺省安装 net-utils 组件。取而代之的工具是 ss 和 ip 。假如你真的、真的很需要 ifconfig 和 netstat,你可执行 yum install net-utils。
更多请参考:
https://wiki.centos.org/zh/FAQ/CentOS7#head-d04a9f331b47791774aefd7c11371934e7350ab3
Send Large Packet by Dpdk Pktgen
场景
测试qinq 发包,但是tcpreplay是没法带vlan tag的。所以需要用pktgen发送qinq包。
问题
qinq双层vlan tag,有些包大小超过了1518字节,pktgen不支持。
解决方案
修改 dpdk-2.1.0/x86_64-native-linuxapp-gcc/include/rte_ether.h:
#define ETHER_MAX_LEN 1522
重新编译DPDK,Pktgen,重新加载DPDK驱动
资料
- DPDK2.1.0:
http://dpdk.org/browse/dpdk/snapshot/dpdk-2.1.0.tar.gz
- Pktgen2.9.5:
http://dpdk.org/browse/apps/pktgen-dpdk/snapshot/pktgen-dpdk-pktgen-2.9.5.tar.gz
Capture QinQ Large Packets
最近遇到一个QinQ的问题,总结一下。
对QinQ协议的交换机做Span,tcpdump抓包后发现,有一些包大小为1522字节,这些包都被网卡丢掉了。仔细排查后发现,网卡对于>1518的包,统一丢掉处理了。
简单的解决办法,就是将网卡的mtu增大,设置为1508或者直接1600,就OK了。
事情虽小,但还是有不少知识点的,归纳一下:
QinQ
简介
IEEE 802.1ad或称为QinQ、vlan stacking。是一种以802.1Q为基础衍生出来的通讯协定。
QinQ报文有固定的格式,就是在802.1Q的标签之上再打一层802.1Q标签,QinQ报文比正常的802.1Q报文多4个字节。这4个字节用作外层标签,即运营商网络的公网VLAN Tag。原802.1Q的Tag用作内层标签,即私网VLAN Tag。
可以参考这张图:
https://zh.wikipedia.org/wiki/IEEE802.1ad#/media/File:TCPIP802.1ad_DoubleTag.svg
QinQ的出现,扩充了原始的vlan个数,由4094 -> 4094*4094。
QinQ的作用,在大规模组网时,或者建立Paas云时,可以允许不同的租户设置相同的vlan id。
并不是所有的交换机都支持QinQ的,QinQ只是一个草案,需要交换机厂商的支持。
下面从wiki上摘抄一个典型例子:
Acme及XYZ分别在Seattle及Tacoma有一间分公司,并借由SP的L2 VPN网络连线,而他们的子公司都使用相同的LAN。 换句话说,我们可以假设,Acme使用VLAN 100-200并透过SP连结两间子公司的网络;XYZ也使用VLAN 100-200并使用SP的网络连结子公司。
而对SP而言,则必须想办法区隔Acme及XYZ的资料,使其有办法通过SP的网络并分别送至各自的子公司。
解决办法就是,使用VLAN STACKING来区隔Acme及XYZ的资料。
当Acme送出资料时,SP使用QinQ并给予该资料一个独特的SPVID 1001,使其能通过SP的网络并流向另外一间子公司,当到达子公司则移除该SPVID,该资料便能依照原始的VLAN ID进行传送。而XYZ送出资料时,SP则使用SPVID 1002来区隔。
包长
QinQ比正常的报文多了4个字节,所以QinQ报文,在链路层,最大包长到了1522个字节。
标准的Ethernet V2中,IP报文最大不超过1500字节,加上DA+SA+TYPE+DATA+PAD, 链路层的以太网帧最小为60字节,最大为1514字节,如果是802.1q,带有vlan tag,会有1518字节。
QinQ的最大包长明显超出了,在大多数网卡驱动中,默认配置下,这种包是会被丢弃掉的。好在交换机会自动处理这种情况,确保包最终到我们的网卡时,是符合Ethernet V2的。
但是直接对交换机端口做Span,网卡便傻掉了。
阅读linux tg3驱动源码发现,丢弃此类包的判断是很简单的:
10188 /* MTU + ethernet header + FCS + optional VLAN tag */
10189 tw32(MAC_RX_MTU_SIZE,
10190 tp->dev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
10191
http://lxr.free-electrons.com/source/drivers/net/ethernet/broadcom/tg3.c#L88
所以只要把网卡的mtu改改大就可以了:
ifconfig ethx mtu 1600 up
再说说以太网帧的大小
根据rfc894的说明,以太网封装IP数据包的最大长度是1500字节,也就是说以太网最大帧长应该是以太网首部加上1500,再加上7字节的前导同步码和1字节的帧开始定界符,具体就是:7字节前导同步码 + 1字节帧开始定界符 + 6字节的目的MAC + 6字节的源MAC + 2字节的帧类型 + 1500 + 4字节的FCS。
按照上述,最大帧应该是1526字节,但是实际上我们抓包得到的最大帧是1514字节,为什么不是1526字节呢?
原因是当数据帧到达网卡时,在物理层上网卡要先去掉前导同步码和帧开始定界符,然后对帧进行CRC检验,如果帧校验和出错,就丢弃此帧。如果校验和正确,就判断帧的目的硬件地址是否符合自己的接收条件(目的地址是自己的物理硬件地址、广播地址、可接收的多播硬件地址等),如果符合,就将帧交给“设备驱动程序”做进一步处理。这时我们抓包的软件才能抓到数据,因此,抓包软件抓到的是去掉前导同步码、帧开始分界符、FCS之外的数据,其最大值是6 + 6 + 2 + 1500 = 1514。
以太网规定,以太网帧数据域部分最小为46字节,也就是以太网帧最小是 6 + 6 + 2 + 46 + 4 = 64。除去4个字节的FCS,因此,抓包时就是60字节。当数据字段的长度小于46字节时,MAC子层就会在数据字段的后面填充以满足数据帧长不小于64 字节。由于填充数据是由MAC子层负责,也就是设备驱动程序。不同的抓包程序和设备驱动程序所处的优先层次可能不同,抓包程序的优先级可能比设备驱动程序更高,也就是说,我们的抓包程序可能在设备驱动程序还没有填充不到64字节帧的时候,已经捕获了数据。因此不同的抓包工具抓到的数据帧的大小可能不同。(比如,wireshark抓到的可能没有填充数据段,而sniffer抓到的就有填充数据段)
那么以太网帧格式一共有多少种呢
历史上以太网帧格式有五种:
1 Ethernet V1
这是最原始的一种格式,是由Xerox PARC提出的3Mbps CSMA/CD以太网标准的封装格式,后来在1980年由DEC,Intel和Xerox标准化形成Ethernet V1标准
2 Ethernet II即DIX 2.0
Xerox与DEC、Intel在1982年制定的以太网标准帧格式。Cisco名称为:ARPA。
这是最常见的一种以太网帧格式,也是今天以太网的事实标准,由DEC,Intel和Xerox在1982年公布其标准,主要更改了Ethernet V1的电气特性和物理接口,在帧格式上并无变化;
Ethernet V2出现后迅速取代Ethernet V1成为以太网事实标准; Ethernet V2帧头结构为6bytes的源地址+6bytes的目标地址+2Bytes的协议类型字段+数据。 常见协议类型如下:
- 0800 IP
- 0806 ARP
- 0835 RARP
- 8137 Novell IPX
- 809b Apple Talk
如果协议类型字段取值为0000-05dc(十进制的0-1500),则该帧就不是Ethernet V2(ARPA)类型了,而是下面讲到的三种802.3帧类型之一;Ethernet可以支持TCP/IP,Novell IPX/SPX,Apple Talk Phase I等协议;RFC 894定义了IP报文在Ethernet V2上的封装格式;
下面给一张图,就对这种帧格式一目了然了:
+-----+-----+------+-----+-------+------+------+-------+
|PR |SD |DA |SA |TYPE |DATA |PAD |FCS |
+-----+-----+------+-----+-------+------+------+-------+
|56b |8b |48b |48b |16b |<=1500|不够 | 32b |
| | | | | | |填充 | |
+-----+-----+------+-----+-------+------+------+-------+
在每种格式的以太网帧的开始处都有64比特(8字节)的前导字符,如图所示。其中,前7个字节称为前同步码(Preamble),内容是16进制数0xAA,最后1字节为帧起始标志符0xAB,它标识着以太网帧的开始。前导字符的作用是使接收节点进行同步并做好接收数据帧的准备。
-
PR:同步位,用于收发双方的时钟同步,同时也指明了传输的速率(10M和100M的时钟频率不一样,所以100M网卡可以兼容10M网卡),是56位的二进制数101010101010…..
-
SD: 分隔位,表示下面跟着的是真正的数据,而不是同步时钟,为8位的10101011,跟同步位不同的是最后2位是11而不是10.
-
DA:目的地址,以太网的地址为48位(6个字节)二进制地址,表明该帧传输给哪个网卡.如果为FFFFFFFFFFFF,则是广播地址,广播地址的数据可以被任何网卡接收到.
-
SA:源地址,48位,表明该帧的数据是哪个网卡发的,即发送端的网卡地址,同样是6个字节.
-
TYPE:类型字段,表明该帧的数据是什么类型的数据,不同的协议的类型字段不同。如:0800H 表示数据为IP包,0806H 表示数据为ARP包,814CH是SNMP包,8137H为IPX/SPX包,(小于0600H的值是用于IEEE802的,表示数据包的长度。)
-
DATA:数据段 ,该段数据不能超过1500字节。因为以太网规定整个传输包的最大长度不能超过1514字节。(14字节为DA,SA,TYPE)
-
PAD:填充位。由于以太网帧传输的数据包最小不能小于60字节, 除去(DA,SA,TYPE 14字节),还必须传输46字节的数据,当数据段的数据不足46字节时,后面补000000…..(当然也可以补其它值)
-
FCS:32位数据校验位.为32位的CRC校验,该校验由网卡自动计算,自动生成,自动校验,自动在数据段后面填入.对于数据的校验算法,我们无需了解.
事实上,PR,SD,PAD,FCS这几个数据段我们不用理它 ,它是由网卡自动产生的,我们要理的是DA,SA,TYPE,DATA四个段的内容.
所有数据位的传输由低位开始(但传输的位流是用曼彻斯特编码的)
以太网的冲突退避算法就不介绍了,它是由硬件自动执行的.
DA+SA+TYPE+DATA+PAD最小为60字节,最大为1514字节.
以太网卡可以接收三种地址的数据,一个是广播地位,一个是多播地址(我们用不上),一个是它自已的地址.但网卡也可以设置为接收任何数据包(用于网络分析和监控).
任何两个网卡的物理地址都是不一样的,是世界上唯一的,网卡地址由专门机构分配.不同厂家使用不同地址段,同一厂家的任何两个网卡的地址也是唯一的.根据网卡的地址段(网卡地址的前三个字节),可以知道网卡的生产厂家.有些网卡的地址也可以由用户去设定,但一般不需要.
3 Ethernet 802.3 raw帧格式
在Ethernet 802.3 raw类型以太网帧中,原来Ethernet II类型以太网帧中的类型字段被”总长度”字段所取代,它指明其后数据域的长度,其取值范围为:46-1500。
接下来的2个字节是固定不变的16进制数0xFFFF,它标识此帧为Novell以太类型数据帧。
这种格式的来源历史非常晦涩,这是1983年Novell发布其划时代的Netware/86网络套件时采用的私有以太网帧格式,该格式以当时尚未正式发布的802.3标准为基础;但是当两年以后IEEE正式发布802.3标准时情况发生了变化—IEEE在802.3帧头中又加入了802.2 LLC(Logical Link Control)头,这使得Novell的RAW 802.3格式跟正式的IEEE 802.3标准互不兼容;可以看到在Novell的RAW 802.3帧结构中并没有标志协议类型的字段,而只有Length 字段(2bytes,取值为0000-05dc,即十进制的0-1500),因为RAW 802.3帧只支持IPX/SPX一种协议;
4 Ethernet 802.3 SAP帧格式
这种帧格式属于 IEEE 802.3/802.2 LLC 标准。
在Ethernet 802.3 SAP帧中,将原Ethernet 802.3 raw帧中2个字节的0xFFFF变为各1个字节的DSAP和SSAP,同时增加了1个字节的”控制”字段,构成了802.2逻辑链路控制(LLC)的首部。LLC提供了无连接(LLC类型1)和面向连接(LLC类型2)的网络服务。LLC1是应用于以太网中,而LLC2应用在IBM SNA网络环境中。
新增的802.2 LLC首部包括两个服务访问点:源服务访问点(SSAP)和目标服务访问点(DSAP)。它们用于标识以太网帧所携带的上层数据类型,如16进制数0x06代表IP协议数据,16进制数0xE0代表Novell类型协议数据,16进制数0xF0代表IBM NetBIOS类型协议数据等。
常见SAP值:
-
0 Null LSAP
-
4 SNA Path Control
-
6 DOD IP
-
AA: SNAP
-
FE: ISO DIS
-
FF: Global DSAP
……
SAP值用以标志上层应用,但是每个SAP字段只有8bits长,而且其中仅保留了6比特用于标识上层协议,因此所能标识的协议数有限(不超过32种);并且IEEE拒绝为某些重要的协议比如ARP协议定义SAP值(奇怪的是同时他们却定义了IP的SAP值);因此802.3/802.2 LLC的使用有很大局限性;
至于1个字节的”控制”字段,则基本不使用(一般被设为0x03,指明采用无连接服务的802.2无编号数据格式)。
5 Ethernet 802.3 SNAP帧格式
Ethernet 802.3 SNAP类型以太网帧格式和Ethernet 802.3 SAP类型以太网帧格式的主要区别在于:
-
2个字节的DSAP和SSAP字段内容被固定下来,其值为16进制数0xAA。
-
1个字节的”控制”字段内容被固定下来,其值为16进制数0x03。
-
增加了SNAP字段,由下面两项组成
-
新增了3个字节的组织唯一标识符(Organizationally Unique Identifier,OUI ID)字段,其值通常等于MAC地址的前3字节
-
增加了表示上层协议的类型
-
这是IEEE为保证在802.2 LLC上支持更多的上层协议同时更好的支持IP协议而发布的标准,与802.3/802.2 LLC一样,802.3/802.2 SNAP也带有LLC头,但是扩展了LLC属性,新添加了一个2Bytes的协议类型域(同时将SAP的值置为AA),从而使其可以标识更多的上层协议类型;另外添加了一个3Bytes的OUI字段用于代表不同的组织,RFC 1042定义了IP报文在802.2网络中的封装方法和ARP协议在802.2 SANP中的实现;
一点资料
关于802.3 的标准,历史真是晦暗不明,看wiki都看不出个所以然来,我只能简单列举一下资料:
https://en.wikipedia.org/wiki/Ethernet_frame#Novell_raw_IEEE_802.3
http://lostintransit.se/2012/06/06/the-history-of-ethernet-dix-vs-802-3/
一点小tip
Q: MTU最大可以设置为多大?
A: 9000,这是由CRC校验的能力决定的。参考:
https://en.wikipedia.org/wiki/Jumbo_frame
PS:早期的一些网络,比如超通道,可以支持65535的mtu,但是已经湮没于历史风尘中了。
参考:
https://zh.wikipedia.org/wiki/IEEE_802.1ad
https://en.wikipedia.org/wiki/Ethernet_frame
Netcat Command
Netcat能做到的事情太多了,但和tcpdump一个流派,参数多的令人发指,拣常用的几个命令记录一下
场景
Server A: 192.168.100.100
Server B: 192.168.100.101
端口扫描
1
|
|
- 可以运行在TCP或者UDP模式,默认是TCP,-u参数调整为udp.
- z 参数告诉Netcat使用Zero IO,指的是一旦连接关闭,不进行数据交换
- v 参数指使用冗余选项
- n 参数告诉Netcat 不要使用DNS反向查询IP地址的域名
一旦你发现开放的端口,你可以容易的使用Netcat 连接服务抓取他们的banner。
1
|
|
消息传送
两台机器间消息传输
SERVER A:
1
|
|
Netcat 命令在1567端口启动了一个tcp 服务器,所有的标准输出和输入会输出到该端口。输出和输入都在此shell中展示。
SERVER B:
1
|
|
不管你在机器B上键入什么都会出现在机器A上
文件传输
大部分时间中,我们都在试图通过网络或者其他工具传输文件。有很多种方法,比如FTP,SCP,SMB等等,但是当你只是需要临时或者一次传输文件,真的值得浪费时间来安装配置一个软件到你的机器上嘛。假设,你想要传一个文件file.txt 从A 到B。A或者B都可以作为服务器或者客户端,以下,让A作为服务器,B为客户端。
SERVER A:
1
|
|
SERVER B:
1
|
|
这里我们创建了一个服务器在A上并且重定向Netcat的输入为文件file.txt,那么当任何成功连接到该端口,Netcat会发送file的文件内容。
在客户端我们重定向输出到file.txt,当B连接到A,A发送文件内容,B保存文件内容到file.txt.
没有必要创建文件源作为Server,我们也可以相反的方法使用。像下面的我们发送文件从B到A,但是服务器创建在A上,这次我们仅需要重定向Netcat的输出并且重定向B的输入文件。
B作为Server
SERVER B:
1
|
|
SERVER A:
1
|
|
目录传输
发送一个文件很简单,但是如果我们想要发送多个文件,或者整个目录,一样很简单,只需要使用压缩工具tar,压缩后发送压缩包。
如果你想要通过网络传输一个目录从A到B。
SERVER A:
1
|
|
SERVER B:
1
|
|
这里在A服务器上,我们创建一个tar归档包并且通过-在控制台重定向它,然后使用管道,重定向给Netcat,Netcat可以通过网络发送它。
在客户端我们下载该压缩包通过Netcat 管道然后打开文件。
如果想要节省带宽传输压缩包,我们可以使用bzip2或者其他工具压缩。
SERVER A:
1
|
|
通过bzip2压缩
SERVER B:
1
|
|
使用bzip2解压
加密你通过网络发送的数据
如果你担心你在网络上发送数据的安全,你可以在发送你的数据之前用如mcrypt的工具加密。
SERVER A:
1
|
|
使用mcrypt工具加密数据。
SERVER B:
1
|
|
使用mcrypt工具解密数据。
以上两个命令会提示需要密码,确保两端使用相同的密码。
这里我们是使用mcrypt用来加密,使用其它任意加密工具都可以。
克隆一个设备
如果你已经安装配置一台Linux机器并且需要重复同样的操作对其他的机器,而你不想在重复配置一遍。不在需要重复配置安装的过程,只启动另一台机器的一些引导可以随身碟和克隆你的机器。
克隆Linux PC很简单,假如你的系统在磁盘/dev/sda上
SERVER A:
1
|
|
SERVER B:
1
|
|
打开一个shell
没有telnet和ssh的时候,可以使用Netcat创建远程shell。
假设你的Netcat支持 -c -e 参数(默认 Netcat)
SERVER A:
1
|
|
SERVER B:
1
|
|
这里我们已经创建了一个Netcat服务器并且表示当它连接成功时执行/bin/bash
假如Netcat 不支持-c 或者 -e 参数(openbsd Netcat),我们仍然能够创建远程shell
SERVER A:
1
|
|
这里我们创建了一个fifo文件,然后使用管道命令把这个fifo文件内容定向到shell 2>&1中。是用来重定向标准错误输出和标准输出,然后管道到Netcat 运行的端口1567上。至此,我们已经把Netcat的输出重定向到fifo文件中。
说明:从网络收到的输入写到fifo文件中
-
cat 命令读取fifo文件并且其内容发送给sh命令
-
sh命令进程收到输入并把它写回到Netcat。
-
Netcat 通过网络发送输出到client
至于为什么会成功是因为管道使命令平行执行,fifo文件用来替代正常文件,因为fifo使读取等待而如果是一个普通文件,cat命令会尽快结束并开始读取空文件。
反向shell
反向shell是人曾经在客户端打开的shell。反向shell这样命名是因为不同于其他配置,这里服务器使用的是由客户提供的服务。
服务端
1
|
|
在客户端,简单地告诉Netcat在连接完成后,执行shell。
客户端
1
|
|
现在,什么是反向shell的特别之处呢
反向shell经常被用来绕过防火墙的限制,如阻止入站连接。例如,我有一个专用IP地址为192.168.100.100,我使用代理服务器连接到外部网络。如果我想从网络外部访问 这台机器如1.2.3.4的shell,那么我会用反向shell用于这一目的。
指定源端口
假设你的防火墙过滤除25端口外其它所有端口,你需要使用-p选项指定源端口。
服务器端
1
|
|
客户端
1
|
|
使用1024以内的端口需要root权限。
该命令将在客户端开启25端口用于通讯,否则将使用随机端口。
指定源地址
假设你的机器有多个地址,希望明确指定使用哪个地址用于外部数据通讯。我们可以在Netcat中使用-s选项指定ip地址。
服务器端
1
|
|
客户端
1
|
|
该命令将绑定地址172.31.100.5。
参考:
http://os.51cto.com/art/201304/388721.htm