所有由kang发布的文章

我的宅家工作经验 ——顺带记录这些年踩过和填过的坑

从2008年开始,工作的变动给了我在家工作的机会,到今年我已经有了差不多12年的在家工作的经历了。近几年随着出差的减少和职位的变动,我在家工作的时间基本超过了90%。这次疫情看到许多朋友陆续开始主动或者被迫在家上班,遇到了各种各样的问题,也有了许多有趣的经历。忽然想写点东西,来记录一下我这十多年在家工作踩过的一些坑和一些简单的经验,分享给大家,也欢迎大家分享些自己的经验经历给我。

先说说在家工作的好处

  1. 缩短通勤时间。尤其是大城市,交通总是个大问题,哪怕距离公司/单位再近,总要花些时间往返吧
  2. 有更多的时间照顾家人。节省下来的通勤时间不只是能用来工作的,记得分给家人一些。
  3. 有卧铺的办公室。懒人,不多解释了。
  4. 可以按照自己习惯的环境来布置办公区。我的东西摆放不一定是整齐的,但是所有最常用的东西都可以放在伸手就可以拿到的位置。
  5. 节省公司资源。公司可以少租办公区,开设共享办公区给临时去办事的员工即可。

当然,在家工作也有许多的坑,比如随时可能被家人打扰(家人真的是容易好心帮倒忙,工作的时候真不需要有人送水送吃的,思路被打断了要花更多的时间才能完成工作);比如网络可能忽然会故障,如果正好在连线开会的关键时刻 ,耽误事情不说至少会惊出一身汗;再比如工作时间其实很难控制,早上睁开眼就上班了,夜里躺床上闭眼才算下班,真忙起来没日没夜。

在此我愿意分享一些自己在家工作的经验给大家,基本都是我自己踩过的坑以及如何应对解决的,内容分为以下四部分:工作环境、工作时间的分配、电话会议、我常使用的软件。

工作环境

  1. 创造一个基本不会被打扰的工作环境
    • 事先和家人沟通清楚,工作时没有特别紧要的事情,请勿打扰,更不要过来围观。
    • 环境相对安静。即使家人说话,也不会影响到正常的工作;同样和同事语音交流的时候也不会影响到其他家人休息。
  2. 网络接入稳定
    • 如果长时间在家工作,一定一定一定选个靠谱的ISP
    • 时刻记住,现在手机还有4G/5G网络可以作为备份,事先测试一下如何用手机网络接入,不要等到出故障的时候忙手忙脚忘记了怎么切换到用手机网络。
    • 工作的时候尽量就别下载东西了,睡觉休息的时候拿自己家的机器(工作用公司的机器,娱乐用自己的设备)怎么下载也不会耽误事情
  3. 保持健康,健康最重要,尤其现在这种时刻
    • 选用一个舒适的椅子:这年头比较靠谱的公司一般都在办公桌椅上不会太吝啬,各种所谓的人体工程学设计让员工坐的舒服工作效率也会提升。但是家里的座椅很可能不是给长时间办公设计的。选择一个适合办公使用的并且自己实际试用感觉舒服的椅子很重要。网上的各种评测只能做为参考,强烈建议自己实际去试试看再选择。
    • 高度合适的桌子:保持平视即可看到显示屏,不用抬头不用低头,千万不要凑合事。如果高度不合适,考虑一下是否垫高一点点电脑,或者接个外置显示器,要么买个支架。如果不是平视的状态,几分钟甚至一两个小时可能都不会太有感觉,但是一旦时间更长了,颈椎很可能会疲劳,进而肩颈都有可能会不舒服。如果凑合的时间更长了,肩颈都有可能会不舒服。
    • 桌子椅子的高度要匹配:胳膊应该基本是水平的状态即可触碰到键盘、鼠标,使用鼠标键盘的时候手腕不要长时间悬空。如果高度不匹配,手腕和肘部时间长了很可能会疲劳。
    • 每一小时站起来走走,至少5分钟:这个非常重要,而且绝对可以提升工作效率。如果怕忘记,设置个闹钟提醒。长时间坐着不动会有健康风险,如果不信请自己搜索“经济舱综合征”。如果要吃东西喝水,建议站起来走过去拿,而不是放在工作台上随时吃喝(想长胖的可以忽略最后这部分,但是每小时站起来走走还是有必要的)。

工作时间的分配

  1. 提前安排可以不被打扰的大块时间给需要长时间才能完成的工作。许多公司没有经理和员工不在同一地点工作的经历。我自从2008年为Cisco服务后,我的经理和我就一直不是一个国家的人,甚至不在一个时区;配合我的团队和我也有十多个小时的时差。作为经理要记得分配完工作后员工需要有不被打扰的时间来完成工作,不要搞文山会海;作为员工要记得哪些事情要在什么时间完成。这个需要非常自觉,记得到点交差。
  2. 保持不被短信、微信、电话分心。即使在家工作,手机也可以考虑保持静音。只要不是在等待非常紧要的消息,没有必要去因为收到了一条短信,来了一个电话,收到一个微信消息就中断工作去看。我的微信经常几百条未读消息,直到每天夜里睡前再去批一下微信“奏折“,最重要的是我不用微信办公,工作上的事情用公司自己的IM系统或者电子邮件来沟通就好。
  3. 每天留出时间来总结工作。每天快下班的时间留时间出来检查是否有工作遗漏了,是否有紧要的事情需要加班处理。重要的事情可以设置提醒。

电话会议

在家办公很可能会用到电话会议系统。我们用的是公司自己的WebEx,其他类似的系统还有很多,我就不一一举例了,大同小异。这里我不讲电话会议的技术,只分享从用户角度看的一些使用经验。

  1. 提前安装好电话会议需要的软件,并且做好测试。如果是第一次使用或者组织员工/客户/合作伙伴参加电话会议,建议在正式开会前安排一次甚至几次测试。经历几次,各种能想到的和不能想到的事情都有可能会发生。
  2. 不发言的时候保持静音状态。最好是手机/笔记本麦克风、电话会议app上都设置为静音。你永远不知道哪些看似很小的噪音会被带入到会议系统并且传递给所有人。我曾经在电话会议中听过的噪音有(但不限于)笔记本的风扇声、沉重的呼吸声(无聊到打呼噜睡着了?)、电路接触不良的电流声、开关门的声音、喝水吃东西的声音、火车鸣笛开过的声音、汽车的喇叭声、街道上枪战的枪声……
  3. 发言时保持好先后顺序。女士优先、领导优先、新人优先,怎么优先都行。电话会议中讨论问题的时候很可能会几个人同时想表达意见,最好是会议主持者可以协调,或者两个同时想说话的人自己协调好谁先说。同时说话的结果是最终谁也听不明白,这不是在同一个会议室里比谁声音大就算赢。如果非要同时表达意见,通常电话会议系统里面的聊天窗口还可以打字。
  4. 发言时保持好恰当的音量。最好能提前测试语音的效果,即使测试了发言的时候最好也问一下大家是否可以听清楚,这样避免因为语音效果不好还要重复讲刚刚讲过的话。
  5. 分享PPT/桌面看清楚了再分享。开会前关掉所有不相关的App,并且提前打开所有你可能想分享的内容、页面、浏览器、PPT、App。分享桌面或者App给参会者的时候记得看清要分享的app再共享出来。我曾经看到过被错误分享出来的个人Email、求职简历(不知道那位后来找到新工作了没有)、私密照片(真不是故意的吧)、正好在对话的聊天窗口(嗯,我们确实不在背后议论别人)。
  6. 视频。注意,通常的电话会议系统的视频是不带美颜功能的,也不会自动给参会者换合适的衣服。下半身穿短裤开带视频的电话会应该没人管,上半身至少得着装得体,女生该画皮的记得画皮。另外记得视频中出现的所有背景都会被参会人注意到。开会的时候保持个相对干净简洁的背景给摄像头。当然不建议家人从可以被摄像头照到的地方走过,会影响其他参会者对你正在讲的内容的注意力。

我常使用的软件

办公用

  1. Office 365 + SharePoint: 主要用来邮件收发、文档协作编辑,电脑手机都可以使用
  2. Cisco WebEx + Cisco WebEx Teams: 电话会议+即时消息软件+VoIP电话,电脑手机都可以使用
  3. Cisco AnyConnect: VPN连接到公司的内网访问部分资源,电脑手机都可以使用
  4. Greenshot: 免费的屏幕截图软件
  5. Everything: 免费的本地文件搜索软件,比Windows自己的搜索要快
  6. VS Code: 好用的编辑器,即使不写代码当编辑器用也挺好。

数据保护用

  1. Cisco AMP for Endpoints: 防病毒、防入侵
  2. Code42 CrashPlan: 数据自动备份 (这么多年也只救过我一次,还是很值了,数据无价。几年前有次SSD忽然彻底坏了,公司电脑上的数据全丢,靠每天的自动备份外加云端的存储几乎所有数据都找回来了)

在家办公有好有坏,真正实际体验过之后不是所有人都会喜欢看似很美好的在家办公,也不是所有公司都会接受员工在家办公。

以上分享希望能够帮助到因为疫情,宅在家办公的朋友们。期待疫情早日结束,一切都尽快回归正轨。

10年CCIE纪念,反思及展望

CCIE 10 years
CCIE #17564 Kang Liu

前几天考完了CCIE的笔试做重认证,今天登陆CCIE portal看到可以使用这个可以给“老人”用的新的logo了。是啊,已经10年了……

又读了一遍10多年前写的那一系列文章:

从2005年开始定了目标,2006-2007年一共考了2个笔试,4次lab,最终拿到了2个CCIE认证。那时候除了每天的日常工作和网络改造项目可以作为实践准备之外,又花了上千小时的时间去学习和做实验。

看着那些文章,回忆起来10年前的那一段学习和考试的经历就好像一段梦一样,那时候可以很专注的学习、练习,即使中途遇到了失败和挫折也能很快爬起来继续努力。

拿到CCIE认证只是努力之后结果,10年之后再回忆起来,我真的很享受那个学习和准备的过程,有谁不愿意能专注的去完成好一件自己喜欢去做的而且自己又觉得有意思的事情呢?

10年之后的我,工作和10年前几乎完全不同了。现在的工作是产品经理,产品经理更多的要解决的是人的问题。相对于人的问题,技术问题通常更容易解决吧!不过不可否认,技术背景对我现在的工作还是非常有帮助的——能理解客户和研发讲的那些技术术语,能更清楚的了解并沟通客户的需求(只要时间足够并且目标已经达到了,想谈产品就谈产品,想谈技术就谈技术,我才不绕圈呢),甚至偶尔还可以给研发讲讲某个技术到底是怎么回事(其实除了“老技术”之外,很多新技术我也是被问到了才现学的,但是有了之前的知识储备,我理解的就能比你快,而且也有信心给你讲明白,嘿嘿)。

嘚瑟和纪念的话就写这么多,再写下一些反思和展望。

以前在准备CCIE的时候,曾经在NetPro论坛上看到过这样的一段话,也写下了 Be a real CCIE这个帖子

In most situations, when someone obtain a CCIE, it tells me that person is willing to go through the pain and sacrifice to obtain this achievement and therefore, deserve a lot of my respect

10年前的我,也许没有完全理解这段话,或多或少的只关注到了那些技术和所谓pain and sacrifice。

现在再反思一下10年前的那段经历,除去学习知识之外,更多的是自己主动的走出了所谓的”舒适区/comfort zone”,去挑战自我并创造了更多更大的机会。

10年之前的我想不到10年之后现在自己做的这份工作。再过10年的我呢? CCIE 10年只是个开始,写篇文章小小的记录和庆祝一下,再出发吧!

用vba批量调整word文件的字体

其实是年前遇到的破事,现在终于有时间记录一下是怎么解决的了。

遇到的问题:一大堆的.docx文件用了莫名其妙的中文字体,造成所有中文字都挤在一起,根本没法看。

处理方法:设定文件字体为宋体,并且将字体嵌入到文件中。顺便调整一下章节前后的空白。

由于文件数量比较多,实在是懒得一个一个去手工处理,于是想起了很多年前玩过的“宏/macro”。以下是代码,如果有需要随意拿走用。这段宏代码会处理目录下所有的文件,将正文、页眉页脚字体都设置为宋体,并且去掉段落前后的空白。

Sub Macro1()
 Dim vDirectory As String
    Dim oDoc As Document
    vDirectory = "C:\some_dir\"
    vFile = Dir(vDirectory & "*.*", vbNormal)
Do While vFile <> ""
Set oDoc = Documents.Open(FileName:=vDirectory & vFile)

ActiveDocument.SetCompatibilityMode (wdWord2010)
ActiveDocument.BuiltInDocumentProperties("Author") = "liukang"

ActiveDocument.Range.Font.Name = "宋体"
With ActiveDocument.Sections(1)
.Footers(wdHeaderFooterPrimary).Range.Font.Name = "宋体"
.Headers(wdHeaderFooterPrimary).Range.Font.Name = "宋体"
.Footers(wdHeaderFooterFirstPage).Range.Font.Name = "宋体"
.Headers(wdHeaderFooterFirstPage).Range.Font.Name = "宋体"
End With
With ActiveDocument.Sections(1).Range.ParagraphFormat
        .SpaceBeforeAuto = False
        .SpaceAfterAuto = False
        .WordWrap = True
End With
    
    ActiveDocument.EmbedTrueTypeFonts = True
    ActiveDocument.SaveSubsetFonts = True
    ActiveDocument.DoNotEmbedSystemFonts = False
    ActiveDocument.Save
    ActiveDocument.Close
    vFile = Dir
Loop
End Sub

 

 

PPPOE ON CISCO ISR 871W 以及DEBUG输出分析

周末的时候翻出来了一台Cisco 871W 路由器,为了榨干闲置设备的每一份能力,我用这个设备替代了家里的一台家用级小路由器实现了PPPoE 接IPv4 + Tunnel Broker方式接入 IPv6 + 多SSID WiFi。

本文记录的是这个小方案的第一部分,实现PPPoE拨号(以及对PPPoE过程的一些研究),后续几天空闲时再继续写后面的部分。

871W是一台相对老的路由器(已经停售),但是本文中用的软件是相对比较新的IOS15.1,配置命令对其他使用IOS15的ISR路由器可以作为参照。

➡  *本文(以及本blog中其他正文部分文字)涉及内容仅代表个人,与公司及日常工作完全无关。

总体想要达到的目标

  • PPPoE拨号连接到Internet (本文)
  • 保证IPv4 到互联网的连通 (对内网做DHCP,在出口做NAT) (已实现,待续)
  • 多SSID 提供WiFi接入,以便将家里的实验设备和日常设备分开 (已实现,待续)
  • 通过tunnel broker实现IPv6接入, 包括WiFi也要有IPv6支持 (已实现,待续)
  • 对IPv6 提供基本的安全保护,禁止外界访问内部的IPv6地址 (已实现,待续)
  • 其他企业级设备能支持但是家用级设备不支持的功能…… (待开发……)

使用的设备

Cisco ISR 871W 路由器,软件版本Cisco IOS Software 15.1(4)M8

拓扑及连线

非常简单,就不画图了,871W上的Fa4 (WAN口)连接 ONU的一个以太口,Fa0口连接家里的PC。

设备配置

用ISR路由器实现PPPoE拨号

注意:我用的ISP服务是包月的,因此完全没有考虑“不用时”自动断线的问题。

参考Configuring PPP over Ethernet with NAT,但是由于我使用的IOS是15.1版,因此命令有些细微却别,比如我完全没有做vpdn-group那部分。

配置如下,Fa4口为WAN口连光猫(ONU):

interface FastEthernet4
 no ip address
 duplex auto
 speed auto
 pppoe-client dial-pool-number 1 dial-on-demand
 no cdp enable
!

interface Dialer0
 ip address negotiated
 ip mtu 1492
 encapsulation ppp
 dialer pool 1
 dialer-group 1
 ppp pap sent-username <username> password 0 <mypassword>
 no cdp enable
!

上面配置是通过pap方式发送PPPoE的用户名密码,实测北京联通的光纤接入可用。用chap方式倒是不行,推测应与ISP那端的设置有关(后面通过debug命令得到了证实)。

接通之后执行”show interface dialer 0″可以up/up状态,并能看到获取的IP。

jsr#show int dialer 0
Dialer0 is up, line protocol is up (spoofing)
 Hardware is Unknown
 Internet address is <some ip>/32
……

对PPPoE更多的一些探索及debug命令

如果好奇PPP的认证过程,可以试试看”debug ppp authentication“命令,想看看PPP的协商过程可以用”debug ppp negotiation”。

注意:生产网慎用debug命令,自己自学(折腾)就多看看debug命令的输出吧…… LCP和NCP (IPCP)到底都做了些什么,在debug的输出里面看的很清楚。

有两篇文档可以作为辅助,以便更容易的读懂debug的输出:

  1. Troubleshooting PPP (CHAP or PAP) Authentication
  2. Understanding debug ppp negotiation Output

执行”clear ppp all”命令可以强制打断并重建PPPoE连接。

首先想看看研究一下为啥chap失败,执行debug ppp negotitation之后再执行”clear ppp all”得到了一堆的输出,摘录一段在这里:

.May 6 16:21:06.558: PPP: Alloc Context [851CAE40]
.May 6 16:21:06.558: ppp96 PPP: Phase is ESTABLISHING
.May 6 16:21:06.558: Vi1 PPP: Using dialer call direction
.May 6 16:21:06.558: Vi1 PPP: Treating connection as a callout
.May 6 16:21:06.558: Vi1 PPP: Session handle[FE000022] Session id[96]
.May 6 16:21:06.558: Vi1 LCP: Event[OPEN] State[Initial to Starting]
.May 6 16:21:06.558: Vi1 LCP: O CONFREQ [Starting] id 1 len 15
.May 6 16:21:06.558: Vi1 LCP: AuthProto CHAP (0x0305C22305)
.May 6 16:21:06.558: Vi1 LCP: MagicNumber 0x2C9EB206 (0x05062C9EB206)
.May 6 16:21:06.562: Vi1 LCP: Event[UP] State[Starting to REQsent]
.May 6 16:21:06.586: Vi1 LCP: I CONFREQ [REQsent] id 1 len 10
.May 6 16:21:06.586: Vi1 LCP: MagicNumber 0xB43B2631 (0x0506B43B2631)
.May 6 16:21:06.586: Vi1 LCP: O CONFACK [REQsent] id 1 len 10
.May 6 16:21:06.586: Vi1 LCP: MagicNumber 0xB43B2631 (0x0506B43B2631)
.May 6 16:21:06.586: Vi1 LCP: Event[Receive ConfReq+] State[REQsent to ACKsent]
.May 6 16:21:06.586: Vi1 LCP: I CONFREJ [ACKsent] id 1 len 9
.May 6 16:21:06.586: Vi1 LCP: AuthProto CHAP (0x0305C22305)
.May 6 16:21:06.586: Vi1 LCP: O CONFREQ [ACKsent] id 2 len 15
.May 6 16:21:06.586: Vi1 LCP: AuthProto CHAP (0x0305C22305)
.May 6 16:21:06.586: Vi1 LCP: MagicNumber 0x2C9EB206 (0x05062C9EB206)
.May 6 16:21:06.586: Vi1 LCP: Event[Receive ConfNak/Rej] State[ACKsent to ACKsent]
.May 6 16:21:06.586: Vi1 LCP: I TERMREQ [ACKsent] id 4 len 4
.May 6 16:21:06.586: Vi1 LCP: O TERMACK [ACKsent] id 4 len 4
.May 6 16:21:06.590: Vi1 LCP: Event[Receive TermReq] State[ACKsent to REQsent]
.May 6 16:21:06.590: %DIALER-6-UNBIND: Interface Vi1 unbound from profile Di0
.May 6 16:21:06.590: Vi1 PPP: Block vaccess from being freed [0x10]
.May 6 16:21:06.594: Vi1 PPP DISC: PPP Renegotiating
.May 6 16:21:06.594: PPP: NET STOP send to AAA.
.May 6 16:21:06.594: Vi1 LCP: Event[DOWN] State[REQsent to Starting]
.May 6 16:21:06.594: Vi1 PPP: Unlocked by [0x10] Still Locked by [0x0]
.May 6 16:21:06.594: Vi1 PPP: Free previously blocked vaccess
.May 6 16:21:06.594: Vi1 PPP: Phase is DOWN

参考Understanding debug ppp negotiation Output这里可以知道PPP的协商过程是如下图所示:

PPP phase transitions
PPP phase transitions

上面debug输出的就是Establishing到Down的这段,原因其实就是LCP协商失败。

上面输出比较重要的两段单独拿出来看看:

.May 6 16:30:48.539: Vi1 LCP: I CONFREQ [ACKrcvd] id 2 len 18
.May 6 16:30:48.539: Vi1 LCP: MRU 1492 (0x010405D4)
.May 6 16:30:48.539: Vi1 LCP: AuthProto PAP (0x0304C023)
.May 6 16:30:48.539: Vi1 LCP: MagicNumber 0xF5FD2887 (0x0506F5FD2887)
.May 6 16:30:48.539: Vi1 LCP: O CONFNAK [ACKrcvd] id 2 len 13
.May 6 16:30:48.539: Vi1 LCP: MRU 1500 (0x010405DC)
.May 6 16:30:48.539: Vi1 LCP: AuthProto CHAP (0x0305C22305)

” I CONFREQ”是ISP那边送来的,大概意思就是说我要用PAP方式做验证好不好?MTU是1492。”O CONFNAK”是我的router在说”我要用CHAP做验证,MTU 1500″。而且这个过程在不断重复,这要是在现实生活中估计俩人早就该打起来了……好在对”Magic Number”两边还是能好好的协商的……

在经过多次之后失败后(我这里看到的是15次)debug输出中会出现这样一句:

.May 6 16:31:12.759: Vi1 LCP: Sent too many CONFNAKs. Switch to CONFREJ
.May 6 16:31:12.759: Vi1 LCP: O CONFREJ [ACKrcvd] id 7 len 12
.May 6 16:31:12.759: Vi1 LCP: MRU 1492 (0x010405D4)
.May 6 16:31:12.759: Vi1 LCP: AuthProto PAP (0x0304C023)

如果说”CNFNAKs”是路由器“稍显含蓄”的表达对部分协商的内容拒绝且我同意的方式是下面的,你看看如何;那”CONFREJ”表示路由器“真急了”,直接说对下面这些你说的我不同意。

根据上面看到的结果,乖乖的把验证方式修改成pap,然后再看看debug的输出:

.May 6 17:11:44.174: Vi1 LCP: Event[Receive ConfAck] State[REQsent to ACKrcvd]
.May 6 17:11:46.159: Vi1 LCP: O CONFREQ [ACKrcvd] id 3 len 10
.May 6 17:11:46.159: Vi1 LCP: MagicNumber 0x2CCCFF0F (0x05062CCCFF0F)
.May 6 17:11:46.159: Vi1 LCP: Event[Timeout+] State[ACKrcvd to REQsent]
.May 6 17:11:46.159: Vi1 LCP: I CONFACK [REQsent] id 3 len 10
.May 6 17:11:46.159: Vi1 LCP: MagicNumber 0x2CCCFF0F (0x05062CCCFF0F)
.May 6 17:11:46.159: Vi1 LCP: Event[Receive ConfAck] State[REQsent to ACKrcvd]
.May 6 17:11:47.115: Vi1 LCP: I CONFREQ [ACKrcvd] id 2 len 18
.May 6 17:11:47.115: Vi1 LCP: MRU 1492 (0x010405D4)
.May 6 17:11:47.115: Vi1 LCP: AuthProto PAP (0x0304C023)
.May 6 17:11:47.115: Vi1 LCP: MagicNumber 0xF9D28078 (0x0506F9D28078)
.May 6 17:11:47.115: Vi1 LCP: O CONFNAK [ACKrcvd] id 2 len 8
.May 6 17:11:47.115: Vi1 LCP: MRU 1500 (0x010405DC)
.May 6 17:11:47.115: Vi1 LCP: Event[Receive ConfReq-] State[ACKrcvd to ACKrcvd]
.May 6 17:11:47.119: Vi1 LCP: I CONFREQ [ACKrcvd] id 3 len 18
.May 6 17:11:47.119: Vi1 LCP: MRU 1500 (0x010405DC)
.May 6 17:11:47.123: Vi1 LCP: AuthProto PAP (0x0304C023)
.May 6 17:11:47.123: Vi1 LCP: MagicNumber 0xAD3A4DCE (0x0506AD3A4DCE)
.May 6 17:11:47.123: Vi1 LCP: O CONFACK [ACKrcvd] id 3 len 18
.May 6 17:11:47.123: Vi1 LCP: MRU 1500 (0x010405DC)
.May 6 17:11:47.123: Vi1 LCP: AuthProto PAP (0x0304C023)
.May 6 17:11:47.123: Vi1 LCP: MagicNumber 0xAD3A4DCE (0x0506AD3A4DCE)
.May 6 17:11:47.123: Vi1 LCP: Event[Receive ConfReq+] State[ACKrcvd to Open]
.May 6 17:11:47.151: Vi1 PPP: No authorization without authentication
.May 6 17:11:47.151: Vi1 PPP: Phase is AUTHENTICATING, by the peer
.May 6 17:11:47.151: Vi1 PAP: Using hostname from interface PAP
.May 6 17:11:47.151: Vi1 PAP: Using password from interface PAP
.May 6 17:11:47.151: Vi1 PAP: O AUTH-REQ id 1 len 19 from "<username>"
.May 6 17:11:47.151: Vi1 LCP: State is Open
.May 6 17:11:47.163: Vi1 PAP: I AUTH-ACK id 1 len 36 msg is "Authentication success,Welcome!"
.May 6 17:11:47.167: Vi1 PPP: Queue IPCP code[1] id[1]
.May 6 17:11:47.171: Vi1 PPP: Phase is ESTABLISHING, Finish LCP
.May 6 17:11:47.171: Vi1 PPP: Phase is UP

这回协商的过程就客气多了,先是两边统一好了magic number(部分debug输出过程省略),之后的“对话过程如下”:

  1. ISP那边的设备说“MRU 1492, PAP验证 magic number是…”
  2. 我这边的路由器回答“部分不同意(CONFNAK),MRU 1500如何?”
  3. ISP那边的设备说”MRU 1500, PAP验证,magic number是…”
  4. 我这边的路由器确认方案(CONFACK)并复述了一遍方案

再之后进入了进入”AUTHENTICATING”状态,使用配置好的用户名密码做了身份验证,收到确认后就进入到了”UP”状态了。

再往后就是NCP (IPCP)协商阶段,从ISP那边拿到IP地址等参数了。

对配置的进一步的小改进-调整MTU

如果想要在LCP协商过程中直接接受ISP那边提出的MRU,那么可以在dailer接口下设置 “ppp mtu adaptive”,那么LCP协商阶段就会减少一次“讨价还价”,直接按ISP那边提供的MRU 1492。debug输出如下(完全没有协商使用1500的过程):

.May 6 18:19:44.429: Vi1 LCP: I CONFREQ [ACKrcvd] id 2 len 18
.May 6 18:19:44.429: Vi1 LCP: MRU 1492 (0x010405D4)
.May 6 18:19:44.429: Vi1 LCP: AuthProto PAP (0x0304C023)
.May 6 18:19:44.429: Vi1 LCP: MagicNumber 0x8816C41F (0x05068816C41F)
.May 6 18:19:44.429: Vi1 LCP: O CONFACK [ACKrcvd] id 2 len 18
.May 6 18:19:44.429: Vi1 LCP: MRU 1492 (0x010405D4)
.May 6 18:19:44.429: Vi1 LCP: AuthProto PAP (0x0304C023)
.May 6 18:19:44.429: Vi1 LCP: MagicNumber 0x8816C41F (0x05068816C41F)

然后Dialer接口 上设置ip mtu 1492 (前面其实已经设置了),对内的接口上设置“ip tcp adjust-mss 1452”,具体原因可以参考这里:Cisco IOS IP Application Services Command Reference

实际测试时,我使用的北京联通的网络看似是接受1500的,不修改成1492没有影响我上网使用。仅供参考。

【BASH SCRIPT】在树莓派上用HC-SR501红外感应器触发USB摄像头拍照

5-1假期闲的没事继续折腾树莓派。这次是尝试模拟一个防盗报警器,用HC-SR501 被动红外动作感应器 (Passive Infrared/PIR motion sensor)来触发USB camera拍照。大概的思路就是如果被动红外动作感应器被触发时,则调用USB摄像头连续拍照N次。

使用的设备:

  • 树莓派
  • HC-SR501 被动红外动作感应模块 (工作电压5V,信号输出未触发0V ,触发时3.3V)
  • USB摄像头 (我使用的是Logitech C920,其实完全不用这么高端的……)
  • LED x1
  • 470Ω 电阻 (与LED串联作为保护)
  • 杜邦线
  • 面包板

物理连线

连线之前的考虑:

  1. 许多传感器都没有电源接反的保护,接之前请务必再三确认正确再连接。
  2. 不同设备的数据输出不一定是3.3V的,有些有可能用5V表示1。我是先用万用表又验证了HC-SR501的数据输出是3.3V才敢连接树莓派的GPIO接口的。如果电压不匹配还非要去连接,则行为很可能异常,甚至损坏硬件。

线路连接:

rpi-HC-SR501-300x249
HC-SR501连接树莓派 接线示意图
gpio2_cb
HC-SR501连接树莓派 电路图
  • HC-SR501的电源连接树莓派5V输出,GND连接树莓派的GND,中间的data连接树莓派的GPIO接口,我使用的是11口 (GPIO 17)。
  • USB摄像头连接树莓派的USB接口 (我是实际是连接到USB hub上了)
  • 根据需要有可能要调整HC-SR501上的电位器来调节触发距离和延时
  • 根据需要有可能要调整HC-SR501上的跳线位置来设置允许多次重复触发

检查连线:

目视确认面包线连接正确并且牢固,使用lsusb查看系统是否识别出了USB摄像头,使用 ls /dev/video*  检验USB摄像头的编号。

root@raspberrypi ~ # lsusb
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 1a40:0101 Terminus Technology Inc. 4-Port HUB
Bus 001 Device 005: ID 0bda:8176 Realtek Semiconductor Corp. RTL8188CUS 802.11n WLAN Adapter
Bus 001 Device 006: ID 046d:082d Logitech, Inc.
Bus 001 Device 007: ID 099a:7160 Zippy Technology Corp. Hyper Slim Keyboard
root@raspberrypi ~ # ls /dev/video*
/dev/video0

实现所用的bash脚本

下面脚本其实是通过轮询的方式每间隔1秒(可调)通过sysfs方式查询一下sensor的状态,然后复制sensor状态到另外一个GPIO接口;如果sensor是被触发,则调用fswebcam来实现拍照。

脚本中我尽量将不同功能拆成函数了,尽管这样效率并不是最高的。在init_led和init_sensor函数中,尽管只有1个报警用的LED和1个sensor,我还是用循环的方式去做初始化,这也不是最优的方法。这样做主要是为了以后做多个sensor和多个LED故意预留的。

HC-SR501传感器是通过3.3V输出来表示被触发时的“1”,这个电压驱动LED也足够,我实际测试了,即使不没有树莓派,1个LED连接到HC-SR501的data输出已经可以实现灯光告警,但是在这个时候LED的光线不够亮,而且不连接树莓派也没法去调用USB摄像头拍照了 ?  ……

#!/bin/bash
#A Sample script to demo PIR motion sensor trigger LED and USB camera
#Written by Kang Liu (http://www.liukang.com)
#You have the freedom to use and/or modify the script, and the freedom to distribute modified and therefore derivative script.
#USB video camera device
videodev="/dev/video0"

#gpio number for the sensor & LED
redled=18
sensor=17

#second(s) between each check
waitperiod=1

#photo settings
photorepeattimes=3
resolution="800x600"

#Directory to store captured photos
directory="/tmp"

#Init GPIO sysfs
#Set default as "Off" for LEDs
init_led ()
{
 for i in $redled
 do
 if [ ! -d /sys/class/gpio/gpio$i ]
 then
 echo $i >/sys/class/gpio/export
 fi
 echo "out" >/sys/class/gpio/gpio$i/direction
 echo 0 >/sys/class/gpio/gpio$i/value
 done
}
init_sensor ()
{
 for i in $sensor
 do
 if [ ! -d /sys/class/gpio/gpio$i ]
 then
 echo $i >/sys/class/gpio/export
 fi
 echo "in" >/sys/class/gpio/gpio$i/direction
 done
}
init_led_sensor ()
{
 init_led
 init_sensor
}

#Turn off LED(s) before exit and unexport the sysfs
cleanup()
{
 init_led_sensor
 for i in $redled $sensor
 do
 if [ -d /sys/class/gpio/gpio$i ]
 then
 echo $i > /sys/class/gpio/unexport
 fi
 done
 exit 0
}

capture_photo()
{
 for (( c=0; c<$photorepeattimes; c++ ))
 do
 filename=$directory/$(date -u +"%d%m%Y_%H%M-%S").jpg
 fswebcam -d $videodev --timestamp "%Y-%m-%d %H:%M:%S (%Z)" -r $resolution $filename
 sleep 1
 done
}

check_activity()
{
 sensor_status=`cat /sys/class/gpio/gpio$sensor/value`
 #Mirror sensor status to another GPIO
 echo $sensor_status > /sys/class/gpio/gpio$redled/value
 #If sensor is triggered,capture photo
 if [ "$sensor_status" -eq 1 ]
 then
 capture_photo
 fi
}

init_led_sensor
trap cleanup INT TERM EXIT
while :
do
 check_activity
 sleep $waitperiod
done

实验后考虑的改进

  1. 如果不想在屏幕上看到每次拍照时执行的细节,可以考虑为fswebcam加上-q参数,将脚本中的fswebcam命令修改成如下:
    fswebcam -q -d $videodev --timestamp "%Y-%m-%d %H:%M:%S (%Z)" -r $resolution $filename
  2. 树莓派的SD卡空间有限,图片的贮存位置在脚本中默认写的是/tmp目录,当然通过Linux挂载NFS/Samba (NT Folder)/云端等等对这段脚本而言,都仅仅是在系统中的某个目录。因此这里就没有特别去在图片存储方面再多考虑了,利用Linux系统本身的能力即可实现将存储“网络化/云端化”。
  3. 本文是用bash脚本方式实现功能的,上面代码只是做功能演示,效率并不高。如果用C去写一段代码,当传感器被触发后,用中断的方式触发告警动作可能会是比轮询更好的选择。留待以后有时间再去琢磨。
  4. 这次我使用的HC-SR501 传感器并不足够敏感。做完所有测试之后,我故意试了试从远处以很慢的速度接近传感器,其实只要足够慢是可以不触发报警的……如果真的要用来做防盗报警器,估计还需要用更灵敏的传感器,甚至将不同种类的传感器进行结合使用。总体而言,这其实是一个非常非常简单的实验。这个实验中使用的传感器也应该是几乎最简单最入门的了,只有0(未触发)和1(触发)两个状态。写这个脚本仅是利用树莓派将传感器告警与后续动作连接起来。至于后续动作是亮个LED灯,还是拍照,甚至是打出去电话、记录日志、发短信、带动继电器做通/断电动作等都是可以实现的。等日后有更实际些的应用再看怎么做了。

对比用SHELL SCRIPT和C语言API操作RASPBERRY PI GPIO的速度

对Raspberry Pi的GPIO在shell script里面可以直接用sysfs的方式进行操作,也可以调用gpio命令来进行操作,还可以用API来进行操作。今天做了个实验对比sysfs方式、第三方gpio命令以及C语言API操作对效率的影响。

昨天写的文章里面提到了用GPIO来控制LED灯的显示,今天其实是突发奇想,想看看用第三方gpio命令来操作和直接操作sysfs的效率到底有多大的区别。

物理连线

连线和昨天写的文章里面的连线方法基本一样,只是在GPIO管脚和GND之间跨接了一个可以测频率的万用表(UNI-T UT136D)。

Shell Script 响应速度测试

测试脚本

#!/bin/bash
#Written by Kang Liu (http://www.liukang.com)
#You have the freedom to use and/or modify the script, and the freedom to distribute modified and therefore derivative script.
#Actually in this test, I will only use GPIO 17 (WiringIO 0) (Red LED)
orgled=27
greenled=18
redled=17
init_led()
{
 for i in $orgled $greenled $redled
 do
 if [ ! -d /sys/class/gpio/gpio$i ]
 then
 echo $i >/sys/class/gpio/export
 fi
 echo "out" >/sys/class/gpio/gpio$i/direction
 echo 0 >/sys/class/gpio/gpio$i/value
 done
}

cleanup()
{
 init_led
 for i in $orgled $greenled $redled
 do
 if [ -d /sys/class/gpio/gpio$i ]
 then
 echo $i > /sys/class/gpio/unexport
 fi
 done
 exit 0
}
gpio_ben()
{
 echo 1 > /sys/class/gpio/gpio$1/value
 echo 0 > /sys/class/gpio/gpio$1/value
 #gpio write 0 1 #method 4
 #gpio write 0 0 #method 4
}

init_led
trap cleanup INT TERM EXIT
while :
do
 #gpio_ben 17 #method 2, method 4
 echo 1 > /sys/class/gpio/gpio17/value #method 1
 echo 0 > /sys/class/gpio/gpio17/value #method 1
 #gpio write 0 1 #method 3
 #gpio write 0 0 #method 3
done

方法1:直接调用sysfs控制通断

脚本中默认没有注释掉的就是方法1,相当于用下面命令来操作gpio实现让电路通断:

while :
do
 echo 1 > /sys/class/gpio/gpio17/value #method 1
 echo 0 > /sys/class/gpio/gpio17/value #method 1
done

实测频率在1.1kHz左右。目测LED基本感觉不到闪烁。

测试结果照片如下,最后两位数字在不断跳动。

万用表测试GPIO接口频率 (Shell Script)

方法2:用shell脚本中的函数调用sysfs控制通断

相当于用下面命令来通过自定义函数gpio_ben操作gpio,实现电路通断:

【BASH脚本】通过LINUX SYSFS调用GPIO实现LED显示RASPBERRY PI内存占用率

这几天弄了个树莓派(Raspberry Pi)玩,装了个Linux。树莓派的GPIO其实非常容易调用,甚至可以直接通过Linux的sysfs来读写GPIO接口的状态,周末空闲的时候写了段bash Shell Script来控制LED灯来展示Linux的内存占用率。这只是个很简单的bash脚本,主要来示意一下如何通过Linux sysfs来调用GPIO来操作LED,通过修改脚本其实可以实现更多的功能,例如显示CPU的温度是否过高等。

我使用的硬件设备:

  1. Raspberry Pi
  2. LED x3 (不同颜色)
  3. 470Ω 电阻 x3 (用来为LED降压)
  4. 杜邦线 (母-公) x3 (用来连接树莓派的GPIO到面包板)
  5. 面包板 x1

第一步:用gpio命令验证物理连线

gpio命令是需要安装WiringPI之后才有的,默认系统不带。安装之后用root权限(sudo)执行 gpio readall,将得到类似下面的结果:

root@raspberrypi:~# gpio readall
+----------+-Rev2-+------+--------+------+-------+
| wiringPi | GPIO | Phys | Name | Mode | Value |
+----------+------+------+--------+------+-------+
| 0 | 17 | 11 | GPIO 0 | OUT | Low |
| 1 | 18 | 12 | GPIO 1 | OUT | Low |
| 2 | 27 | 13 | GPIO 2 | OUT | Low |
| 3 | 22 | 15 | GPIO 3 | IN | Low |
| 4 | 23 | 16 | GPIO 4 | IN | Low |
| 5 | 24 | 18 | GPIO 5 | IN | Low |
| 6 | 25 | 22 | GPIO 6 | IN | Low |
| 7 | 4 | 7 | GPIO 7 | IN | Low |
| 8 | 2 | 3 | SDA | IN | High |
| 9 | 3 | 5 | SCL | IN | High |
| 10 | 8 | 24 | CE0 | ALT0 | High |
| 11 | 7 | 26 | CE1 | ALT0 | High |
| 12 | 10 | 19 | MOSI | ALT0 | Low |
| 13 | 9 | 21 | MISO | ALT0 | Low |
| 14 | 11 | 23 | SCLK | ALT0 | Low |
| 15 | 14 | 8 | TxD | ALT0 | High |
| 16 | 15 | 10 | RxD | ALT0 | High |
| 17 | 28 | 3 | GPIO 8 | ALT2 | Low |
| 18 | 29 | 4 | GPIO 9 | ALT2 | Low |
| 19 | 30 | 5 | GPIO10 | ALT2 | Low |
| 20 | 31 | 6 | GPIO11 | ALT2 | Low |
+----------+------+------+--------+------+-------+
root@raspberrypi:~#

Phy对应的是针脚的位置, GPIO对应的是GPIO的编号。需要注意两点:

  1. 实际执行这个命令后Raspberry Pi显示的GPIO编号很可能和我的不一样,要仔细看好然后再看看要用哪个编号。
  2. GPIO的编号和物理针脚不一定是顺序对应的,比如我这次要用的是针脚11, 12, 13,对应的GPIO编号是17, 18, 27。当然如果要用wiringPi的逻辑pin的话就是0, 1, 2,但是我这次不打算用wiringPi,只用sysfs来实现对LED的控制。

第二步:连接线路

注意:连线前断电,连好之后请再三确认之后再通电!

raspberrypi-led-gpiov2
Raspberry Pi Control LED by using GPIO
gpio2_bb
GPIO LED 树莓派 面包板接线示意图

gpio_circuit_diagram-900x647
GPIO 连接LED 电路图

连接好线之后,请再次目视检查确认线没接错,特别是0v (GND)一定不要接错!再三确认之后再通电,进入Raspberry Pi的命令行界面测试接线是否正确。刚刚接好线的时候LED是不会像上图那样亮起来的,可以执行下面命令看看LED是否会亮(注意要有root权限):

root@raspberrypi:~# echo 17 >/sys/class/gpio/export
root@raspberrypi:~# echo "out" > /sys/class/gpio/gpio17/direction
root@raspberrypi:~# echo 1 >/sys/class/gpio/gpio17/value

修改GPIO的数字,依次测试。如果一切正常,那么三盏LED灯会依次亮起来,记住每个数字对应的LED的颜色。

第三步:编写脚本通过sysfs调用GPIO实现用LED灯展示内存占用率

我写的脚本如下,如果你愿意,你可以随意使用/修改后再使用/分发。

#!/bin/bash
#A Sample script to check memory usage and reflect the result by LED.
#Written by Kang Liu (http://www.liukang.com)
#You have the freedom to use and/or modify the script, and the freedom to distribute modified and therefore derivative script.
#gpio number for the LEDs
orgled=27
greenled=18
redled=17

#precentage of available memory
memfreehigh=60
memfreelow=30

#seconds to wait between each check
waitperiod=10

#Init GPIO sysfs
#Set default as "Off" for LEDs
init_led()
{
 for i in $orgled $greenled $redled
 do
 if [ ! -d /sys/class/gpio/gpio$i ]
 then
 echo $i >/sys/class/gpio/export
 fi
 echo "out" >/sys/class/gpio/gpio$i/direction
 echo 0 >/sys/class/gpio/gpio$i/value
 done
}

#Set LED value
#Parameter is the GPIO number for the LED
set_led()
{
 led_status=`cat /sys/class/gpio/gpio$1/value`
 if [ "$led_status" -ne 1 ]
 then
 init_led
 echo 1 > /sys/class/gpio/gpio$1/value
 fi
}

#Turn off All LEDs before exit
cleanup()
{
 init_led
 for i in $orgled $greenled $redled
 do
 if [ -d /sys/class/gpio/gpio$i ]
 then
 echo $i > /sys/class/gpio/unexport
 fi
 done
 exit 0
}

check_mem_usage()
{
 output=`free |grep Mem|tr -s [:space:]`
 #uncomment the below lines if you want to debug
 #echo $output
 total=`echo $output | cut -d ' ' -f 2`
 used=`echo $output | cut -d ' ' -f 3`
 available=$((100-used*100/total))
 #echo $available% available
 if [ $available -le $memfreelow ]
 then
 #echo "RED"
 set_led $redled
 return
 fi
 if [ $available -ge $memfreehigh ]
 then
 #echo "GREEN"
 set_led $greenled
 return
 fi
 #echo "ORANGE"
 set_led $orgled

}

init_led
trap cleanup INT TERM EXIT
while :
do
 check_mem_usage
 sleep $waitperiod
done

上面的脚本实现每10秒钟检查一次内存占用率(利用free命令),如果可用率高于60%,那么亮绿灯;如果可用率低于30%,则亮红灯。在30%到60%之间时亮橙色灯。在退出程序后,LED都会灭掉。

将上面脚本保存为.sh后缀,然后chmod +x赋予执行权限,再执行就可以了。

对上面的脚本稍加修改也可以实现用LED监控树莓派的CPU温度等等,这里就不一一列举代码了。用Shell获取树莓派的CPU/GPU温度可以参考这里:Raspberry Pi onboard temperature sensors

FAIL2BAN ON UBUNTU

本文主要介绍如何使用 fail2ban 来削弱针对ssh的猜密码攻击。Ubuntu上自带的 fail2ban 默认规则有些小问题,看似不能直接生效。本文对系统自带 fail2ban 规则做了些修改,实际在Ubuntu Linux 14上测试可用。

清明假期的时候闲的没事将主机从AWS迁移出来了,blog平台也换成了WordPress。新的主机在所在的网段被无聊的人扫来扫去(有种回到校园网的感觉),而且有不少尝试对ssh的攻击,本着“不折腾不会死”的做死精神,在新的主机上启用了fail2ban。

新的主机跑的是Ubuntu Linux的,使用系统默认配置的fail2ban之后发现其实是不生效的。上网搜了一下发现不少人在抱怨fail2ban不能用。这周末自己闲在家里稍微研究了一下,原来是Ubuntu默认安装的fail2ban规则和系统auth.log产生的log不能匹配造成的。

简单记录一下让Ubuntu Linux上的fail2ban来阻挡ssh猜用户名/密码的攻击方法:

  1. 保证机器的时间正确(时区也看看),安装fail2ban(参考这里)。
  2. 启用ssh证书认证(对,这个和fail2ban没任何关系,但总比用密码认证安全些),具体参考这里: How To Set Up SSH Keys
  3. 看一下/var/log/auth.log中的sshd的报错,我这里放几个我遇到的比较典型的(student是随便一个用户名,10.1.1.1是任意的一个ip,example.com是任意的域名):
    • Invalid user student from 10.1.1.1
    • Received disconnect from 10.1.1.1: 11: Bye Bye [preauth]
    • Address 10.1.1.1 maps to example.com, but this does not map back to the address – POSSIBLE BREAK-IN ATTEMPT!
    • reverse mapping checking getaddrinfo for example.com [10.1.1.1] failed – POSSIBLE BREAK-IN ATTEMPT!
  4. copy /etc/fail2ban/filter.d/ssh.conf /etc/fail2ban/filter.d/bad-ssh.conf
  5. vi (或者你任何喜欢的文本编辑器,别和我争论这点,我是习惯用vi了)bad-ssh.conf,修改成以下内容:
[INCLUDES]
before = common.conf

[Definition]
_daemon = sshd
failregex = Received disconnect from : .*: Bye Bye \[preauth\]
 Address maps to .* POSSIBLE BREAK-IN ATTEMPT!$
 Invalid user .* from $
 Did not receive identification string from 
 reverse mapping checking getaddrinfo for .* \[\] failed - POSSIBLE BREAK-IN ATTEMPT!$
ignoreregex =
  1. 修改/etc/fail2ban/jail.local,增加下面一段内容
[bad-ssh]
enabled = true
port = ssh
filter = bad-ssh
logpath = /var/log/auth.log
action = iptables[name=sshd, port=ssh, protocol=tcp]
maxretry = 2
bantime = 36000
  1. [optional] 修改 /etc/fail2ban/action.d/iptables-blocktype.conf,我是认为直接drop就好了,对这种无聊的攻击没义务发icmp port unreachable回去
# Option: blocktype
# Note: This is what the action does with rules. This can be any jump target
# as per the iptables man page (section 8). Common values are DROP
# REJECT, REJECT --reject-with icmp-port-unreachable
# Values: STRING
#blocktype = REJECT --reject-with icmp-port-unreachable
blocktype = DROP
  1. 执行service fail2ban restart,注意观察/var/log/fail2ban.log和auth.log,再有攻击发生会能看到类似下面的日志:
2014-04-19 17:47:29,215 fail2ban.actions: WARNING [bad-ssh] Ban 10.1.1.1

如果想要测试自己写的正则表达式是否正确,可以使用fail2ban自带的”fail2ban-regex”来测试,从auth.log中找出自己想匹配的一条日志,然后执行一下这个命令来试试看自己写的表达式是否会匹配即可。例如下面的例子:

root@hostname:~# fail2ban-regex 'Apr 19 18:55:07 hostname sshd[9146]: Received disconnect from 10.1.1.1: 11: Bye Bye [preauth]' 'Received disconnect from '

Running tests
=============

Use failregex line : Received disconnect from 
Use single line : Apr 19 18:55:07 hostname sshd[9146]: Received dis...


Results
=======

Failregex: 1 total
|- #) [# of hits] regular expression
| 1) [1] Received disconnect from 
`-

Ignoreregex: 0 total

Date template hits:
|- [# of hits] date format
| [1] MONTH Day Hour:Minute:Second
`-

Lines: 1 lines, 0 ignored, 1 matched, 0 missed
root@hostname:~#

需要注意,如果日志里面有中括号([])等特殊字符,记得要用正则表达式的转义字符”\”来匹配。要想匹配的更准确些,还可以考虑用上”$”(行尾)”^”行首等等……正则表达式怎么写就不多说了,网上的教程一大堆……

最后还是要多废话几句,fail2ban不能完全阻止所有的针对ssh的攻击,只能靠暂时封禁来削弱这种攻击的强度。定期看系统日志,发现潜在异常并且根据日志来进行相应的调整是系统管理员必须要做的事情。

在CME上更换Cisco IP Phone的背景图片

终于可以趁着端午节假期休息一天了……这段时间真是忙坏了

整理一下最近做的一件有意思的事情:如何利用ISR路由器上的Cisco Unified Communications Manager Express来更换IP电话的背景图片。

先来一张更换之后的实际效果图:

配置CME的步骤我就略过不说了,没有任何特殊的地方。
要更换IP电话背景图片需要先制作图片,建议先查询一下Cisco IP电话的说明手册,看看想要更换图片的IP电话支持的图片大小是多少,不同电话支持的图片大小可能是不一样的。

上面照片中的是Cisco 7945 IP电话,支持的背景图片大小是320×212,为此需要准备2个图片,一个大小是320×212作为实际背景图片,另外一个大小是80×53 (长和宽都是原始图片的1/4)作为预览图片。

接下来需要将图片文件传送到路由器的flash中,经过后续的一些步骤之后,IP电话就可以通过tftp方式找到这些文件。 一般是将图片存放在flash中的”Desktops/320x212x16/” 其实放在哪里都无所谓,等一下可以通过配置TFTP服务器的时候指明文件位置。

使用文本编辑器编写一个名为List.xml的文件(注意文件名大小写),内容类似下面的内容,传送到图片文件同一个目录里面:
<CiscoIPPhoneImageList>
<ImageItem Image=”TFTP:Desktops/320x212x16/Cisco_Logo_s.png” (预览图文件名)
URL=”TFTP:Desktops/320x212x16/Cisco_Logo.png”/> (实际背景图文件名)
</CiscoIPPhoneImageList>
文件可以写很多段,以便同时支持多个背景图片文件

接下来在路由器上做配置
tftp-server flash:/Desktops/320x212x16/Cisco_Logo.png alias Desktops/320x212x16/Cisco_Logo.png (实际图片文件)
tftp-server flash:/Desktops/320x212x16/Cisco_Logo_s.png alias Desktops/320x212x16/Cisco_Logo_s.png (图片预览)
tftp-server flash:/Desktops/320x212x16/List.xml alias Desktops/320x212x16/List.xml (配置文件)

针对7945来说alias后面的目录名是固定的,文件名除了List.xml之外其余都是上传图片文件的文件名,不同路由器可能是不同的;具体可以查询Cisco文档,或者在路由器上做debug tftp event(注意尽量不要在生产网设备上执行debug命令)来看电话试图请求哪个文件。 有些网上的案例文档没有给出alias及随后的参数,实际测试表面这个参数是必须的,因为启动CME之后默认的tftp-server文件目录不一定是flash了,电话配置的xml文件也不一定是存在flash里面的嘛。

完成上面步骤之后剩下的步骤只需要在电话上操作,按下电话上的配置按钮,选择1. User preference,然后选2. Background (不同电话可能不一样),这时电话会对路由器发起tftp请求(如果在路由器上启用了debug tftp event这时就会看到电话首先请求List.xml文件,然后请求图片预览文件),然后在电话上就可以看到默认的背景图片以及新传送到tftp-server上的图片了。 在电话上选中想要用的图片,然后在点save就可以了。之后即使重新启动电话选中的图片也不会丢失。

需要注意,所有的图片文件都会保存在电话的flash里面,如果想要从电话中删除这些自定义的图片,则需要重置电话恢复出厂设置才可以。