新史太阁记-一个不世出的产品经理成长史

因为刚看完了《丰臣秀吉》,想找些其他描写日本社会文化历史以及现状的书籍时,一不小心就看到了这本司马辽太郎的《新史太阁记》。

书的内容基本沿袭大的历史框架,不再有秀吉嗜好女色的大篇幅描写,也没有更多的民间传说的影子,总之更贴近历史的脉络,少了些民间的历史玄幻。小说从秀吉的少年开始,一直到巅峰时期,戛然而止。

这期间陆陆续续看了些秀吉的书,还有影视材料,最震撼的不仅是日本战国的武士情怀,还有出于职业背景的条件反射:如何成为一个伟大的产品经理。注意,我特意使用了伟大一词。

对于技术人的成功,我一直坚持认为:技术-产品-公司,这3个梯度的进阶和成功,才是真正的成功。而这三个体度的难度系数相差远不止一个数量级。而要完成这样的转变,你要有开阔的眼界和思维,要理解社会的发展和人性的需求,要有理想主义者的坚持和奉献牺牲。

我看到过很多技术牛人,他们热衷于 一系列能让人感觉新奇的技术,但是他们却很难理解要为产品或者公司的成功去奉献和坚持,他们更关注短期的自我的收获,缺乏长远的对产品成功,公司成功的认知和追求。会新奇的技术是有价值的,但最终为大众提供价值的是产品本身,这个涵盖技术,设计,交互,服务等,远不是很多技术人想象的因为一个所谓的技术就能怎样。

好吧,扯远了,说一说我从秀吉的故事中总结的一个伟大的产品经理的一些要素吧。

我们一般说的产品经理的价值:

清晰准确的产品定义:功能需求定义,目标用户群体定义,商业模型定义,生命周期定义。
秀吉:每一次的战事秀吉都有着清晰的产品定义,他知道自己最终要的是臣服和胜利,所以他会选择合理的战术方略,而不是简单粗暴野战屠杀,故事里面每一战事秀吉都有着很深入的分析和合适的方案提出,而这一切都是因为他对目标有着清晰的定义,能外交的就不兵刃,能围城的就不破城,因为我要的是胜利,而不是摧毁对方和杀戮。

技术质量的保障:依赖自身的知识背景,采用合理的管理方式,选择正确的技术架构,来保证可靠,低成本,快速的实现产品解决方案。
秀吉:故事里的秀吉每一此都能根据天时地利提出一套低成本而且行之有效战事方略,这些战术的方案最终保证了秀吉在保存力量的情况下取得成功。

沟通协调:在遇到资源问题或者对外需求时,能高效的沟通和获取资源保证团队的进度需求,在收到内部领导的不合理需求时,也能顶住压力和风险,保证团队能按照正确的方式和方向去开发。
秀吉:毋庸置疑,历史上真正的秀吉无论跟信长还是家康比,秀吉无疑是一个善于沟通,善于外交的政治家。

士气目标管理:产品经理不是简单的让相关的设计开发坐在一起开发就好了,要了解每个人的性格,让所有人都能认识到产品项目的价值,都能认识到自身的价值,充分体现自豪感和主动性,从而发挥巨大的价值,最终形成团队超强的战斗力。在取得阶段的进步或者奖励时,也能适时的鼓励团队,鼓励成员,保证团队高昂的士气,从而取得不可能达到的成绩。
秀吉:秀吉的部下基本都是草莽出身之所以能取得最后的高水准的胜利,得益于秀吉队伍高昂的士气,无论是通过金钱的奖励还是封地的奖赏。

背黑锅:大家都是凡人,不是神仙,到最后难免有错误的决定或者失败的计划,产品经理的另外一个用户就是替大家来背黑锅。因为产品经理就是产品和团队的负责人,失败了,产品经理是最大的责任人,无需客观理由。

而要成为伟大的产品经理,还需具备:

对产品方向执着的信念:无论是早期对信长的神一般的信仰还是后面对胜利的信念,秀吉能走这么远,能在众多的力量中崛起,最重要的是秀吉是一个理想主义者,靠执着的信念在一次次的战事和政治中取得成功。

克服一切困难创造条件解决问题的能力:面对困难时,在其他人迟疑时,秀吉积极承担,克服不利,最终树立了在织田家的声望和地位,比如美浓之战的善后工作。

愿意付出一切保证产品成功的奉献精神:秀吉对每一次的任务都是倾尽全力的,可以说为达目标不择手段,甚至去做一些被人唾骂的残忍行为。

最终,秀吉从一个茅屋少年成为日本战国时代的一代枭雄,成为了一个伟大的产品经理。

丰臣秀吉

加藤广 著
曹宇 译
2014年第一版

一直一来对日本文化都很感兴趣,小时候看的很多日本动画片,还有宫崎骏,北野武(很喜欢的另一个原因是北野武事务所一直是支持贾樟柯电影的,这两个人我都很喜欢),黑泽明等大师的很多作品。记得小时候(80年代)看的一个引进的似乎叫阿香的很长的日本电视剧(里面就有主人公日常的生活和日本社会的大量描写),那时候就对日本留下了深刻的印象。

本书是作者根据大量史记和民间传说编撰的伪纪实传记小说,每一章节开始都有摘引自史记史实的事件作息行踪记录,然后精心地穿插着作者编撰的精彩故事。

因为本书大量的日本人名和地名,本文不想写成准确的读书笔记,只想把自己读完的大概思绪以作记录,想了解详情的还请移步小说。

羽柴秀吉(藤吉郎)出身贫苦,从小体弱,身高不显,少年丧父。其父是个会计,擅长算数,因担心儿子未来生计,从小训练藤吉郎算数,使得秀吉具有缜密而灵活的头脑(纵观一生,真正使其收益的应该是其谦逊和不断学习的精神)。因为穷苦,藤吉郎早期走街串巷以卖针为生,积累了大量的地理和世俗情报,后加入当时还未一统的织田信长手下,因助其逃过劫杀而得到赏识和重用,从普通士卒成为大将大名。起初秀吉最多也只能算是众多武将中一个算是能干的普通将领,排名不是很靠前,但靠一系列的战役和英勇表现,再加上所谓的天意暗示(有高僧推荐,有手相暗示)等,最终成为一代枭雄。

军事和谋略方面,秀吉是天才,越是大事件大场面越能显示出其超常人的思维和冷静决绝的判断。
个人生活和精神情感方面,其一生都是大写的悲剧,从未停止。
社会方面,幕府时代的日本是一个家臣社会,武士忍者只能对主公负责,是主公的私有财产和工具。女性普遍不被尊重,没有地位,导致可以随便被欺凌(权势)。信长时代,西方基督教已经大举入侵日本,引进了西方的知识和理念,当然紧随其后的就是铁甲舰,洋枪洋炮和梅毒。
生活物资方面,由于日本特殊的地理资源限制,日常生活清贫(从赏赐上就能看出来)。天皇家室受人尊敬,但迫于幕府威胁和生活所迫,忍辱负重,利益权谋。

半兵卫,秀吉文化水平不高,但依赖其谦逊的态度和其不嗜杀的作风,赢的半兵卫的辅佐,半兵卫乃不世奇才,类似中国的诸葛卧龙。从而使的秀吉从众臣中显身而出,鹤立鸡群。半兵卫从一开始就帮秀吉规划好了天下,再临终前,又帮秀吉赢得了官兵卫,官兵卫助其实现战术的胜利。可以说没有半兵卫,秀吉此生最多也就大名了,战死或者被清除掉。
官兵卫,因秀吉受半兵卫建议,救下官兵卫儿子,在救出官兵卫后,得到了官兵卫的感激和追随。虽然半兵卫被描述成先知之谋略,但官兵卫的实际作用丝毫不逊于半兵卫,他是实际帮助秀吉夺取天下的人,真实的水平深藏不露。官兵卫早年信仰基督,晚年改信佛教。
秀长,秀吉的弟弟,能干,但缺乏谋略,是大臣和秀吉之间的缓冲带。50多岁就死了,使的晚年的秀吉缺少了心腹很支持。
将右卫门,秀吉的左膀右臂,没有这个踏实而放心的的伙伴和下属,秀吉的事业轨迹将大大不同,他也是秀吉唯一想说和敢说心里话的干将。事业和心灵的好基友。
小六,跟将右卫门一样,得力干将,但是跟秀吉的关系没有将右卫门近。
秀次,秀吉的侄子,从知识和才干方面,是唯一一个看似能继承秀吉衣钵的人,可惜被陷害,株连。但其和妻女3p的事情很是让人不解。
光秀,信长公的忠臣,因不甘信长暴戾和对天皇的不尊,而想取而代之,却被秀吉渔翁得利。
德川家康,从不多的描写中可以看出其老奸巨猾,能屈能伸,心狠手辣(弑其子)。
宁宁,秀吉正房,忍受秀吉鬼混,终其一生陪伴和追随的人,是一个真正爱着秀吉的女人。宁宁是个下等人的女儿,但秀吉并没有在显赫时休掉宁宁,也没有加以恶意相待和冷落,并且对夫妻关系作必要的经营和维护,可以说是秀吉自己用行动获取了宁宁最终的支持和陪伴。
龙子,极其崇拜秀吉,是其心灵伴侣,在精神和肉体上都得到秀吉的信赖和喜欢。
茶茶,一个淫贱,有手腕,心狠手辣的女人。然而平心而论,最终她也许都只是她母亲的一个工具,是一个悲剧的影子。

和善,不拘小节。不忌主仆繁文缛节,平时打成一片,深受部下拥戴和喜爱。
施财而好才。先后招揽了了半兵卫,官兵卫,将右卫门,小六等当世之才。秀吉不像其主公信长那么吝啬,受封后尽将财物封地分与下属,赢得部下的效力和忠心。在急行军后,开库散银,犒赏全军。懂得用眼前的利益赢得未来的利益。善招揽人才,善用人才,这也是其脱颖而出的关键。
善谋略,不嗜杀。其大多的战术都是围城,水淹威胁,一夜城恐吓等,即使在拥重兵的情况下也不擅使暴力强攻,大部分的城池都是接受投降,甚至城主留任。
好色。以现在的眼光看是很好色,但综观后面的秀次等的表现就可以明白,秀吉的水准也许只是普通水准略高而已,毕竟权高位重嘛,获取资源门槛低。整个当时的日本都是这样的风气,也不能单怪秀吉。
谦虚好学。无论是早年对大家意见的细心听取还是后面的对诗词的虚心学习,都说明真正使秀吉强大而可怕的正是其一生的学习态度和追求。

秀吉把信长作为对手,但在除掉对方后,获得权力后,却心怀愧疚被家康持以把柄以及临死都无法释怀,恰恰是日本家臣以及武士精神的体现,在中国历代的权利斗争中很少有此方面的感情顾虑。

秀吉的整个人生就像一颗坠落的流星,从冉冉发光,到光芒万丈,最后到燃烧殆尽。秀吉用其一生的经历,说明了即使一个出类拔萃的人在面对权力和金钱时,也很难保持自我。你未疯狂,因为你还没有尝过权力的滋味。

追求金钱和权力的过程可以让一个人得到满足感,但金钱和权力本身并不能满足人精神层面的空虚和欲望。

羽柴秀吉,藤原秀吉,后来天皇赐姓丰臣,也就是大家耳熟能详的丰臣秀吉。

如果秀吉可以生育,如果他没有过早的疏远忠臣干将,如果他不是用现在的方式杀死信长,如果他当年追杀了家康,如果他没有杀秀次,如果他没有宠幸茶茶,如果他坚持收养了天皇的弟弟,秀吉的人生又应该是怎么样的呢?

但生活,没有如果。。。

东京散步

作者:藤田宜永
译:兴远

译者的水平还是不错的,让整个故事叙述显得生动,细腻,阅读起来很舒服。
建议阅读时长:1-2天

首封上写的是:幸福来时总是慢得让人难以察觉,而不幸却是毫无预兆地轰然降临。

故事讲述了一个出身悲惨,处境落魄的年轻人突然接到一个诡异而报酬诱人的陪同散步的生意。在散步的过程中双方互相倾诉心境,途中一起经历了种种怪异而有趣的事件。最终在故事的结尾,主人公得知了生意的真相,也在对方的帮助下实现了自己内心的愿望。故事最终得到了一个令人惋惜而不忍的结局,但真实的生活不就是这样吗,不完美才是我们孜孜以求。

故事娓娓道来,看似缓慢的节奏却引人入胜,结局有点想不到,整个故事在高潮中结束,一气呵成。如果你在一个周末的早上开始阅读,也许在你下午会不经意的发现你竟然一口气看完了整个故事。

从故事中你能了解当时的日本的一部分群体的生活状态和社会现状:高利贷,弹子店,情色店,援交,离家出走,婚内出轨等。通过几个相关人物的人生经历和状态,让人感受到日本特定时代下一部分群体真实的生活。

结尾福原有一段的语言显得很生硬,也许是作者构思小说时的最开始提炼的主题,所以硬生的借福原的嘴表达了出来。

推荐:细读

git 403 Forbidden

现象

error: The requested URL returned error: 403 Forbidden while accessing https://github.com/xxx/xxx.git/info/refs

fatal: HTTP request failed

分析

错误是在一个脚本中操作git时的错误提示,看错误提示初步判断是权限问题,继续google之,发现 : http://stackoverflow.com/questions/19722521/error-the-requested-url-returned-error-403-forbidden-while-accessing 。

解决

参照帖子的思路:

  1. 将https改为ssh访问,直接修改repo对应的隐藏文件.git/config 文件中的url即可。
  2. Generating an SSH key

再次运行脚本,执行成功。

hugo生成文章中不能正确显示中文字数的问题定位

问题发现

在刚切换到hugo博客的时候就发现文章的字数统计是错误的,但是因为当时也没发现有额外的副作用,就暂时懒得理了,毕竟这个只是写作工具,web前端也不是本人长项。

今天在使用多说分享文章的时候发现部分文章分享失败,于是根据分享生成的URL中的数据初步判断是获取文章content时出错了。插件获取了超长的content内容,导致接口调用失败。

问题定位

1. 多说

我们看多说插件中的相关代码:

data-content="{{ .Summary }}" 

多说只是使用了模版中的Summary变量值。

2. Summary

关于Summary变量,我们看Hugo的解释

Hugo-defined: automatic summary split

By default, Hugo automatically takes the first 70 words of your content as its summary and stores it into the .Summary variable, which you may use in your templates.

Pros: Automatic, no additional work on your part.
Cons: All HTML tags are stripped from the summary, and the first 70 words, whether they belong to a heading or to different paragraphs, are all lumped into one paragraph. Some people like it, but some people don't.

从以上的内容看到Hugo只是默认最多取70个词(words),所以这里很明显是取70个词时,实际取出了远远多于70个的内容,导致上面的url出错。

3. 长度错误

从上面我们初步判断是长度的问题。初步查看模版的代码,我们知道长度在模版中使用的是WordCount变量。于是我们查看hugo中WordCount相关的代码hugolib/page.go:

if p.isCJKLanguage {
        p.WordCount = 0
        for _, word := range p.PlainWords() {
            runeCount := utf8.RuneCountInString(word)
            if len(word) == runeCount {
                p.WordCount++
            } else {
                p.WordCount += runeCount
            }
        }
    } else {
        p.WordCount = len(p.PlainWords())
    }

从上面isCJKLanguage的变量名我们就能猜到是判断非英文的路径。简单看下代码,Hugo是有考虑CJKLanguage的问题的,也就是说可能是这个分支没有执行。

4. isCJKLanguage

我们搜索工程,找到isCJKLanguage:https://github.com/spf13/hugo/blob/2c5e4f7640e71d2a193a74e6c41109ec40bc0222/docs/content/content/front-matter.md 中的介绍,于是手动在出错的markdown文件中添加此变量,再次重新执行hugo,发现对应生成的网页中的字数统计的值正确了,分享也不出错了,说明就是字数的统计导致了系统错误。

问题验证了,但是因为博客的文章都是用工具自动从wordpress中生成的,不可能手动一个一个修改,修改工具也显得很死板,最好的方法是从Hugo这侧来找方案。

5. hugo配置文件

顺着上面的思路,开始搜索相关的关键字,发现hugo的配置中还真有相关的配置hasCJKLanguage:https://github.com/spf13/hugo/blob/b7efbdc12f0a96639b445f7920b6477d88beb744/docs/content/overview/configuration.md ,喜出望外,赶紧添加到config文件中重新编译文件,编译后发现并没有生效。于是再次查看源码hugolib/page.go:

if isCJKLanguage != nil {
        p.isCJKLanguage = *isCJKLanguage
    } else if viper.GetBool("HasCJKLanguage") {
        if cjk.Match(p.rawContent) {
            p.isCJKLanguage = true
        } else {
            p.isCJKLanguage = false
        }
    }

从上面的代码看isCJKLanguage 是由HasCJKLanguage开关控制的。

6. HasCJKLanguage

继续看代码,我们看到工程中只有一个地方有设置commands/hugo.go:

viper.SetDefault("HasCJKLanguage", false)

于是尝试修改本地的此行代码,重新编译Hugo。再次用hugo生成所有文章,发现所有文章的长度都正确了,甚是高兴。

再次检查今天发现的分享出错的文章,都全部正常了,舒服!

小米路由器R1D刷机手记

update

2016.12.16:由于文章中的360 网盘的资源挂了,重新更新了tomato的刷机包的路径

缘由

小米路由器R1D已经使用了快一年,一直想刷机,主要因为:

  • 后门问题,请搜索知乎“小米路由器 劫持”,虽然严格讲天朝人民是没有什么隐私,但被人强奸总是很郁闷的。
  • 用了半年后,经常会掉网,很快就自动恢复,有时候莫名其妙手机就掉网开始走移动流量,很郁闷。

    小米路由器R1D

    小米路由器R1D是一款基于博通bcm4709( c )和OpenWRT深度定制的智能路由器。

准备工作

  • 了解基本的linux 常用命令,ssh,root权限等。
  • usb一个,用来制作usb刷机工具。
  • 备份你的拨号账号密码。
  • 一个备用的路由器,刷机有风险,一旦出现变砖,备用路由器至少可以让你继续使用网络,不至于影响正常的网络使用。
  • 一米的短网线,用来直连路由器,当然理论上wifi也是可以的,但是某些rom在进入特定的刷机工具状态时wifi是不可用或者启动有延迟的,有线则方便很多。

刷机的ROM备选

小米路由器是深度定制版的OpenWRT,网上大概搜了一下,可选的有OpenWRT原生系统,DD-WRT和Tomato三种系统可以尝试。

OpenWRT

ROM

首先从官方的硬件支持列表我们并没有看到R1D的支持:https://wiki.openwrt.org/toh/start 。其次从小米论坛和google也没有找到明确支持的rom。

刷机

巧妇难为无米之炊。
结果:放弃

DD-WRT

ROM

从官方的支持列表中:http://dd-wrt.com/wiki/index.php/Supported_Devices ,我们并没有看到R1D的支持ROM。但是我们可以找到非官方的rom,例如:http://bbs.xiaomi.cn/t-10691878

刷机

刷机流程参见:http://www.right.com.cn/forum/thread-143121-1-1.html ,本人尝试多次,均在第6步失败,初步判断是tftp server没有正常启动。

分析原因:原博是在0.4.58的rom上做的验证,本人尝试0.4.58版的USB和web页面升级的方式,均失败。web直接校验失败,USB刷机后,路由器无法正常启动,于是只能采用的最新开发版来验证。猜想是小米硬件做了升级限制或者在软件层面有专门对这个漏洞做修复。

结果:失败。如果有最近刷机成功的兄弟,也望留言指教。

Tomato

ROM

AdvancedTomato是一套基于Tomato的路由器管理界面,其核心是tomato。这个是tomato对应R1D的下载路径:

  1. http://tomato.groov.pl/download/K26ARM

  2. https://bitbucket.org/tsynik/tomato-arm/downloads

本次刷机实际使用的是这个:http://bbs.xiaomi.cn/t-11522784 ,因为有人验证过,并且支持中文,相对风险会小些,实际效果有待日后进一步观察。

说明:

因为文章里面的360的网盘挂了,特将rom重新发布:

链接: http://pan.baidu.com/s/1o8TRooE 密码: qe4j

因为本人验证时已经是很久以前的事情了,所以建议看到的朋友在上面的路径下载最新的版本尝试。

刷机

  1. 升级到最新开发版 :http://miwifi.com/miwifi_download.html
  2. 开ssh,http://www1.miwifi.com/miwifi_open.html
  3. ssh 192.168.31.1,ifconfig得到网卡MAC地址(或者刷机之前在web页面记录下MAC)
  4. 下载tomato固件,见前面的rom部分内容 。
  5. 下载tomato刷机包
  6. 打开CFEEdit.exe,通过菜单打开cfe.bin,修改其中的MAC地址为你的小米路由器的MAC地址,改好后覆盖。
  7. 将cfe.bin、backup.sh、flash-cfe.sh这三个文件放入U盘,插入路由U口。
  8. ssh登录路由器,登陆的账户名和密码参见 http://www1.miwifi.com/miwifi_open.html 。执行:
    nvram set boot_wait=on
    nvram set wait_time=10
    nvram commit
    进入U盘目录:cd /extdisks/sdb1 ,此路径可能会不同,请自行确认。执行:
    ./backup.sh
    ./flash-cfe.sh
    先备份系统文件,在必要时可以手动恢复。
  9. 电脑有线ip设置为192.168.1.1段,通过有线连接局域网端口。
  10. 重启路由,浏览器打开192.168.1.1,刷入tomato固件即可。

刷回小米系统

  1. 将miwifi-stock.bin和小米官网下载的小米路由器最新版U盘刷机包(改名我miwifi.bin)放到U盘中
  2. ssh登录小米路由器,执行命令:
    mtd-write2 /mnt/U盘/miwifi-stock.bin linux
  3. 按复位键,重新接电源,等黄灯闪烁后松开复位键
  4. 几分钟后黄灯常亮,拔下U盘
  5. 浏览器登录小米路由器,通过web页面更新最新开发版。

结果:成功。
启示:按照CFE的思路,理论上也可以来刷DD-WRT,但已经折腾一天了,改日有机会再试吧。

AdvancedTomato 基本安全配置

  1. 修改界面语言,修改管理员名称和密码:系统管理 - 管理员访问
  2. 设置宽带拨号,DHCP,wifi的SSID和密码:基础设置 - 网络
    注意:
    WAN设置:类别为PPPoE,不要勾选“使用DHCP”。
    LAN:默认的DHCP是有问题的,要设置正确的值,客户端才能正确使用外网。
    无线网络:设置WPA/WPA2密码。
  3. 如果为了进一步的安全,建议开启无线过滤:基础设置 - 无线过滤 - 允许以下客户端。手动添加需要wifi访问权限的设备,避免有人搞小动作

AdvancedTomato 服务配置

  1. USB&NAS
    通过设置,我们可以外接USB硬盘了,这个对某些人似乎有点用。
  2. 文件共享
    删除默认的共享,设置你要共享的目录,记得设置身份验证。这样你就可以在局域网使用路由器的1T硬盘了
  3. DLNA服务器
    如果你想在bt下完电影后,直接通过电脑或者手机观看,就要设置这个。设置一下媒体文件的目录,设置完后,DLNA客户端就可以直接在局域网发现媒体资源了。如果需要ios的客户端,你可以在APP store搜索Arkuda。
  4. BitTorrent客户端
    开启后,你可以通过路由器页面给路由器下发bt任务了,它会下载到你指定的路径,如果这个路径支持DLNA,那么下载完,你就可以直接观看大片了。
  5. DDNS+端口转发
    如果你要在远程通过互联网来玩bt,那么就需要继续设置DDNS+端口转发。

最后

如果你是其他型号的路由器,只要是刷相同类型的rom,流程基本相似,希望有帮到大家,也欢迎大家交流。
最后,有图有真相:

AdvancedTomato

刷完后,感觉整个世界都平静了。

其他参考

http://blog.icece.tw/Xiaomi-R1D-1TB-Flash-Tomato

补充:

  1. 关于发热的问题,我觉得原版其实就发热,我自己尝试的135的版本,刷机后感觉网速和发热并没有改善,期望新尝试的朋友继续反馈

LoRa技术介绍

目前看,LoRa是一个在IOT方案领域替换GSM的初步可行方案,主要从距离和功耗两个考虑方面。

介绍如下:
http://www.lora-alliance.org/What-Is-LoRa/Technology
http://www.rfwireless-world.com/Terminology/LoRa-technology-basics.html
http://www.rfwireless-world.com/Terminology/IoT-wireless-technologies.html

芯片厂商目前也已经有了量产的芯片可供评估,成本在1-2个美金。
http://www.microchip.com/design-centers/wireless-connectivity/embedded-wireless/lora-technology
http://www.semtech.com/wireless-rf/lora.html

IPSec生成证书

在很多安全服务中,我们都需要签名的安全证书。

注意 如果不生成证书,后面配置部分的配置中用 pubkey 认证的 conn 都不能用,甚至不能保留在配置中。
每一个完整的 ssl 证书都有一个公钥和一个私钥,它们可以在一起也可以分开放(当然如果你要在网络上传输,肯定只能用公钥)。公钥是在网络上传输的,而私钥是藏好用来和接收到的公钥配对的(因此私钥里也有整个公钥,用来配对)。

生成 CA 证书

生成一个私钥:

ipsec pki --gen --outform pem > ca.pem

没什么好解释的,--outform 一共有三个格式可选,但是另外两个是 der 和 pgp...

基于这个私钥自己签一个 CA 证书:

ipsec pki --self --in ca.pem --dn "C=CN, O=strongSwan, CN=strongSwan CA" --ca --outform pem > ca.cert.pem

这里 --self 表示自签证书,--in 是输入的私钥,--dn 是判别名,--ca 表示生成 CA,其它同上。这里需要解释下判别名:

C 表示国家名,同样还有 ST 州/省名,L 地区名,STREET(全大写) 街道名。
O 表示组织名。
CN 为通用名。
具体见微软的文档:Distinguished Names

生成服务器证书

同样生成私钥:

ipsec pki --gen --outform pem > server.pem

用我们刚才自签的 CA 证书给自己发一个服务器证书:

ipsec pki --pub --in server.pem | ipsec pki --issue --cacert ca.cert.pem \
--cakey ca.pem --dn "C=CN, O=strongSwan, CN=forum.suse.org.cn" \
--san="forum.suse.org.cn" --flag serverAuth --flag ikeIntermediate \
--outform pem > server.cert.pem

这条命令的意思解释下:

ipsec pki --pub --in server.pem
是从我们刚生成的私钥里把公钥提取出来,然后用公钥去参与后面的服务器证书签发(这个是 VPN 连接时候要用的,你不想把私钥也给它吧?那样跟没签证书一样...)。

--issue, --cacert 和 --cakey 就是表明要用刚才自签的 CA 证书来签这个服务器证书。

--dn, --san,--flag 是一些客户端方面的特殊要求:

iOS 客户端要求 CN 也就是通用名必须是你的服务器的 URL 或 IP 地址;
Windows 7 不但要求了上面,还要求必须显式说明这个服务器证书的用途(用于与服务器进行认证),--flag serverAuth;
非 iOS 的 Mac OS X 要求了“IP 安全网络密钥互换居间(IP Security IKE Intermediate)”这种增强型密钥用法(EKU),--flag ikdeIntermediate;
Android 和 iOS 都要求服务器别名(serverAltName)就是服务器的 URL 或 IP 地址,--san。

生成客户端证书

依然是生成私钥:

ipsec pki --gen --outform pem > client.pem

然后用刚才自签的 CA 证书来签客户端证书:

ipsec pki --pub --in client.pem | ipsec pki --issue --cacert caCert.pem \
--cakey caKey.pem --dn "C=CN, O=strongSwan, CN=client" \
--outform pem > client.cert.pem

这时命令行会提示你输入两遍密码,这个就是你的客户端证书密码。

看懂了服务器的,客户端的也就不难理解了。除了没有那一堆特殊要求别的都一样。

客户端证书可以每个客户端签一个,也可以让它们公用一个。是否多签看用途,一般用于区分设备(计费是不用这样的,是用账户来区分的)。

生成 pkcs12 证书(可选)

你可能还想生成一个可以直接导入的 pkcs12 证书(用于手机,诺基亚没这东西还不行):

openssl pkcs12 -export -inkey client.pem -in client.cert.pem -name "client" \
-certfile ca.cert.pem -caname "strongSwan CA" -out client.cert.p12

安装证书

cp -r ca.cert.pem /etc/ipsec.d/cacerts/
cp -r server.cert.pem /etc/ipsec.d/certs/
cp -r server.pem /etc/ipsec.d/private/
cp -r client.cert.pem /etc/ipsec.d/certs/
cp -r client.pem /etc/ipsec.d/private/

CA 证书、客户证书(两个)和 .p12 证书用 FTP 复制出来给客户端用。有几种 Android 配置还需要服务器证书(server.cert.pem)。

docker中的”layers”指的是什么东西

在很多的docker的说明中,我们都能看到“layer”的身影,那么到底什么是”layer“?

参见http://docker-doc.readthedocs.org/en/latest/terms/layer.html中的说明:

When Docker mounts the rootfs, it starts read-only, as in a traditional Linux boot, but then, instead of changing the file system to read-write mode, it takes advantage of a union mount to add a read-write file system over the read-only file system. In fact there may be multiple read-only file systems stacked on top of each other. We think of each one of these file systems as a layer.

简单翻译如下:
当docker加载rootfs时,和传统的linux系统中一样,它是只读的,但是随后,不是将当前文件系统变成可读写,而是利用union mount添加一个可读写的文件系统在当前的只读系统上。实际上将会有很多的只读文件系统叠加在彼此之上。我们将这里的每一层文件系统称之为"layer"。

参考阅读:
https://docs.docker.com/engine/understanding-docker/#how-does-a-docker-image-work
https://www.ctl.io/developers/blog/post/caching-docker-images/