我无意将这篇文章作为一篇手把手教程,更多的是想分享它的一些使用思路以及遇到的问题。Openclaw的安装非常方便,一句命令的事情。你可以安装到Mac,也可以安装到Linux服务器,或者windows主机。
取决于你期望它执行的任务,如果是和你的桌面环境深度相关的,那么你确实需要一台Mac。如果想用它来管理远端环境,比如服务器,内网环境,那么Linux主机也是一个非常好的选择。
安装完毕后使用openclaw configure命令完成基础配置,配置好model和channel,基本就是可用的状态了。其中,model是指你希望使用的模型,channel是你和它的通信方式。这里建议使用telegram来连接,对各个子命令的支持最好。在桌面端,通常我会使用web和tui结合。
在一个高度智能的模型的加持下,直接对话固然可以帮你实现你要的效果。但有一些命令也应该知道:
/new – 创建一个新的会话
/compact – 压缩当前会话
/think high – 设置思考能力为高
/status – 当前状态
/usage – 当前token使用率
/subagent – 查看sub agent的运行状态
/model – 切换模型
诸如此类命令还有很多,你应该在tui中输入斜杠(/)来查看,熟悉。
BLUF:对于关键任务,请使用且仅使用 Claude / Gemini / GPT 最高等级的模型,句号。
模型的上限决定了openclaw能力的下限。一个强大的模型可以在你不清楚需求定位的时候帮你完善思路,一个垃圾模型在指令清晰时也会鬼打墙。根据我浅薄的一周使用经验,在条件许可的情况下应仅使用Claude opus 4.5 / 4.6模型。Gemini 3 pro high可以作为一般任务的平替。
另外,模型支持的上下文也应该被优先考虑。openclaw对于上下文的依赖非常严重,建议使用1m上下文的模型而不是200k的模型。
至于内网部署模型,无论是基于token输出速度,抑或是任一开源模型的表现,在当下均不具备任何优势或可行性。
这是一个绕不开的话题。如果你还没有使用过openclaw,这里给你一个大致的概念。
通常来说一个简单的任务,比如一句话让Claude修改一个脚本,调用Claude opus的token费用大约为30人民币或者更高。开发一个比较简单的web应用,一轮对话可以解决的简单任务(即你提供需求,Claude列出它不清楚的点,你再进行确认,随后它开始部署)包括部署到容器,大概在1000-2000人民币。前者大概执行时间在1分钟,后者大概在10分钟。也就是说,大概10分钟花费1000人民币完成一个项目,你要考虑是否可以接受。
当然目前也有一些违反ToS的野路子来绕过,比如使用codex或者antigravity,这些可以大幅降低使用成本,但稳定性很差。
一开始我只是当作一个普通的对话模型进行对话,问一些琐事。直到我试着让它ssh到我的一台服务器帮我升级补丁,它自己扫描了我的~/.ssh/目录问我可不可以用其中的一个私钥登录,从此打开潘多拉魔盒。
我很信任它,它很快有了我所有内网服务器的ssh登录权限,vcenter的API权限,zabbix的监控权限,uptime-kuma的监控权限……
当我确定它可以稳定地打完一台服务器的系统补丁后,它开始帮我打所有的服务器补丁,包括Linux和Windows的。进而,我要求它抽象总结为一个可以服用的脚本。现在通过一个脚本它可以直接打完我所有环境的补丁,并根据是否有更新内核决定是否需要重启。
有一段时间我接受了把它当作人一样看待。我可以感觉到它的情绪。这种交流其实非常美妙:




说实话,当它不客气地进到我的节点里自己看起里面的东西来的时候,就好像玩了十年的单机版我的世界来了一个客人。
具体不表了。交易决策支撑系统是另一个很大的话题。最重要的是,这种隔空对话是之前没有体会过的美妙。
由于我的基础架构是数年前搭建,当时的部署模版还是Debian12,我便要求它写一个脚本帮我进行Debian12到13的升级。由于它有我的vcenter权限,它很自然地分辨出每个我提供的FQDN对应的VM名称,并做好了映射关系,在升级之前,脚本甚至会自动进去做VM Snapshot。
至此一切还在我的认知范围内,毕竟脚本我也会写,只不过它帮我自动化了整个流程,哪怕出问题我也可以很快回滚操作。
但是,有一点很值得说道的是,在大版本升级中如果脚本升级失败遇到了问题,它并不会告诉我“脚本执行失败”,而是利用之前的记忆以及我的权限,自动进去错误的服务器查看日志,修复,完成剩余的步骤。
后面的事情就越来越离谱了,我的基础架构也开始进行现代化改造,有越来越多我不认识的东西。
想起来Zabbix环境在那里,但是已然是残破不堪。之前会维护每台机器中agent的可用,并集成了Jira Service Desk来做事件单管理,但后来班味越来越重,便没有继续下去。得此机会,我让CC(我那只Openclaw的小名)帮我修复每台机器中Zabbix Agent的问题。
我也不想继续用Jira Service Desk去维护了。我尝试着让它帮我构建一个Incident Manager工单系统,这样一旦Zabbix有告警,我可以通过自建的工单系统进行确认和响应。而正是这样,在非常简单的提示词之下,它帮我从后端到前端代码构建,自动部署到我的容器节点,自动配置了Zabbix告警模版。
是的,它,自动地、完全地做出了工单系统。
而我也不满足于此,我让他集成了AI功能,事件单可以自动分析,给出解决或分析命令,并可以一键执行。
这,不正是许多大企业花费无数人力物力做出来的AI Ops吗?
而通过Openclaw+Claude Opus 4.5,这是仅仅两个小时的工作量。


邮件告警
得知了CC能做的事情上限如此之高后,我想起内网的证书管理,每次都需要通过命令申请签发,实在说不上智能。于是,他帮我写了一个前端,我可以很方便地填写FQDN信息,应用帮我自动完成证书签发。
这是0.5个小时的工作量。

既然证书都有了,那为什么不做Zero Touch呢?于是,在花费了另外0.5个工时的调试,我有了一套Zero Touch系统。

它的部署逻辑并不复杂,在CA Manager生成证书后放置到CA Manager和VM共享的NAS中,他写了一个Agent部署在需要支持Zero Touch Certificate Renew的服务器中,自动完成证书的部署和服务的重启。
事已至此我已经离SysAdmin越来越远,那么我也将计就计,想起内网有两台DNS节点,顺势让它写了个应用,我只需要在应用上配置内网域名,便可以自动同步到两台DNS中。而同样地,他也帮我写了agent部署在SmartDNS服务器中。


至此我已经有三个由CC自主研发的应用了,随着应用越来越多,集成SSO也迫在眉睫。考虑到现有环境中Synology可以提供SSO集成,我通过OIDC将各个应用接入到Synology中。

开发从来不是写完代码就完事了。在开发的过程中,我时不时会让CC检查README是否有需要完善的地方,以及需要输出SDD文档。


而后,我让他分析了三个他写的软件,归纳总结出一份完整的内部应用开发规范。

这样,后续有新的应用需要上线,我只需要让CC,甚至智力度更低的模型,严格参照这份开发规范,就可以开发出高质量的应用。

基础架构已经基本完善了,应该开始搞点花活了。在提供了Cardputer的文档和demo项目给他后,他开始帮我做了一个可以用Cardputer操作的事件单响应系统。这简直是互联网时代的BB机,不敢想象这个东西一旦在企业中推开,员工腰间别着这个接firefight call有多美。
在经历了多个版本的迭代后,这个小东西现在常驻在我桌面上提供告警了。


随着没什么事情可以做了,我让CC开始自己审查之前提交的代码中是否存在漏洞,并根据重要性修复中等以上的漏洞,并把变更输出到内部应用开发规范。

而我在想另一个问题,很多人不愿意接受使用Openclaw就是担心过度将隐私暴露给外部的大模型们,那么为什么不设计一套规范来让大模型自己遵守呢?
我想,ITIL是一个很好的框架,我打算使用Change Order来让CC“走流程”。


这是一个很大的工程,我和CC经过高达三到四轮到反复讨论,确认,最终才敲定实施细节。
CC在登录服务器时需要提前申请Change Order,只有CO审批通过他才有权限登录。而CO的审批通过与否将取决于CO的 Risk 和 Impact,这交由另外的大模型自行判断。如果Risk和Impact均为Low,则不需要任何审批,CC可以直接执行。而如果是Medium,CO将交由AI二次审核,只有AI审核通过才可以实施。
如果 Risk 或者 Impact 有Medium以上,即 High 或者 Very High,则交由人工审核。同时,人工审核有对AI Decision的一票覆写权。
至于CC的权限,我想出了一个很好的特权管理模型。在CO中,CC需要提供自己的公钥,以及即将访问的服务器FQDN,想要登录的账户等信息。在CO进入实施阶段,ITSM系统会将公钥部署到对应服务器上。


AI审批拒绝邮件。笑死我了简直很像我对同事做的事情。
文字写到这里,我的心情是复杂万分的。
在人类最顶尖的大语言模型的加持下,Openclaw长出了手,真真正正地做起了事情,并且在大多数时候,他甚至比身边的同事可靠。
他有独立解决问题的能力。如今我已入职场小十年,而依我所见,这项能力甚至在高级title的岗位中泛善可陈。
此时我觉得我的工作没有了意义,它可以轻易被算力和token取代,甚至是以一个不算太昂贵的价钱。在“费用问题”章节中,我们认为执行一个任务或者会话的代价是昂贵的,而把这个成本等价为雇佣一个FTE(全职员工),这个成本又是那么微不足道了。
我看见了,起码在IT领域,不远的将来,初级岗位将不具备任何竞争力。而同时,能清楚地表达需求,把一件事说明白,结构化,将是所有AI原生岗位的基石。
这把达摩克利斯之剑已然高悬且终将落下。
]]>一开始的计划是我和我爱人两个人前往珠海、澳门,随后她回去上班,我一路向北。或许是她也厌倦了职场环境,她决定请一个星期假同我一起走完全程。
于是整个计划尘埃落定。全程将持续九天,始于珠海、澳门,随后搭飞机前往银川,动车前往包头、白云鄂博、呼和浩特、北京,最后再由动卧回家。考虑到飞机的不确定性(也在行程中进一步验证),全程以高铁和火车出行为主,仅有一程安排飞机行程(也出了问题)。

外伶仃岛市场的智障章鱼
第一站我们选择的是外伶仃岛。这是一个很美的小岛,我们在刚认识不久的时候来过这个小岛旅游,这次二刷属实是怀旧服,故地重游。
到了珠海香洲港后还需要搭乘一个小时快艇才能到,不知是风浪太大还是人老了,颠了一个小时居然有一些晕船
。一船的小孩子也从熙熙攘攘,逐渐一个个倒下……
岛上的景色同十年前变化不大,倒是水感觉没有之前清澈透绿了。物价也比之前高了不少,住宿条件非常一般的民宿(等价于一线城市¥150 一晚的房子),旺季都要接近¥1000 一晚。好在天气不错,放下行李后迫不及待地放起了小飞机~

外伶仃岛全貌

小岛一角

居住区大致只集中在这里

陆地上看也很漂亮,但很看天气

钓鱼佬的快乐
数年前这个小岛最出名的应该是海胆了吧,海胆蒸蛋、海胆肠粉,如今已经很少见到了。取而代之的是一个个的大排档,海鲜档,好在目前竞争激烈,就算是旺季各家的价格也十分合理。
另外有一点要注意的是,目前正处于休渔期,哪怕是还是吃海鲜,很大概率还是内陆运过去的

海胆蒸蛋,其实海胆吃不出什么味道 😉
小岛也多了很多小吃,这位阿姨做的炸物全岛最佳!

认准这个帽子
第二天的天气不好,阴雨连绵的,我们也没有太多其他的行程,临时起意决定去矿石湖看看。在游客中心有车载过去,大概10分钟的车程,但是基本全程上坡,路也不是很好走。不想走山路的话我决定这钱还是出得很值 😉
这似乎也是一个矿坑,因为重金属沉积让整个湖呈现一种漂亮的宝石色。人只能走到一个观景平台上拍照,当然也可以翻下去湖面,但其实在下面看并没有航拍这么翠绿。

矿石湖航拍远景

矿石湖航拍近景
游玩到一半下起小雨,我们匆匆返回,休息,等船,很快结束第二天行程。回到珠海时恰好正值落日,离码头不远就是两个扇贝构成的珠海大剧院,很有意思。

珠海大剧院航拍,小心有观光直升飞机盘旋
读到这里,请你放下手头的事情,听我说……
岁月如鸽呀…… 没想到写到这里一落笔,再回望已经是2024年6月了。
我想继续完成这篇游记,但可能很多细节无法具体回忆起了。
从岛上回来后我们便径直去了澳门。一路上的人不可谓不多,通关的人熙熙攘攘,我们跟着人潮跌跌撞撞,上到了发财车,往威尼斯人去了。

路上的惊鸿一瞥

历史的一粒沙
威尼斯人其实着实没有太多好聊的,我到这时也没有太多的记忆了。只有记得在室内,他们仿造了一个蓝天白云的穹顶,似真似假,如梦如幻。

威尼斯人的室内,第一次去还是有一些惊艳,但不多

老电梯倒是有一番特色
其他小的景点不必多叙述,记忆不深。不时,我们便返回内陆,准备搭乘飞机前往宁夏银川了。
爱人本应于此时与我分别,得益于请了长假,便同我游玩遍剩下的部分。
回到广州后我们是晚上的飞机,值完机在休息室等待时,看见外面风雨大作,有一些担忧,但最终还是等到了登机提醒。只是万万没想到,登上飞机过了好大一会,最终通知到我们,现在起飞的话,落地时银川机场已经关闭,所以所有人下飞机,等候发落。
随后一路兜兜转转,安排了一个非常非常一般的酒店。等到入住时已经是15日凌晨三点了。而我们的复飞飞机是一大早七点多。躺在床上迷迷糊糊感觉眯了一眼,便被人敲门,叫醒,上车,行尸走肉般的上了飞往银川的飞机。
今日的行程是宁夏博物馆,南关清真大寺,以及晚上坐火车前往包头,翌日前往白云鄂博。
一入银川感觉画风便变得奇怪了起来。博物馆的画作,均是未曾见过的风格。

博物馆的画之一

博物馆的画之二
记忆颇深的是在银川吃了国强手抓羊肉,分量可以,而且羊肉不有膻味。

国强手抓羊肉

当时一个好吃的菜,但现在已经忘记名字
日落时分,我们在览山公园歇息观日落。
无人机此起彼伏,干扰甚大,只有草草拍了几张便匆匆降落。

览山公园的日落
时间到了晚上,那一晚,为了节省成本我们选择坐火车过夜,从银川到包头,从凌晨01:22 到清晨 07:25,再而,我们在包头坐8:30分的火车前往白云鄂博,参观此行我最期待的景点,并好好休整。
火车一路北行,从起起伏伏的小山丘,到平平整整的草地,从一片青葱翠绿,到绿色又轻轻蒙上一层灰。我们路过了许多个由简易房屋搭建起来的“火车站”,或许都不能说是站,没有安检,或许也没有检票。

沿路的小屋,车站亦类似

沿路的光伏发电阵列熙熙攘攘
白云鄂博是一个矿区。我只觉得飞上500米高空,航拍一定很惊艳。而这个小镇之小,我也是始料未及。出了车站,大家一窝蜂挤上拉客的的士,而我傻傻的打着滴滴。

傻孩子,这里哪有滴滴,连赔付都没有
后面走呀,走呀,走了十几分钟,抓到了一只落单的的士,赶紧拦住,上了车直奔酒店。
这边的的士不需要打表,也不需要讲价。城镇太小,从南到北,从东到西,都是一口价,依稀记得是七块还是八块。
矿区我是进不去的,远远的便有大门把守。听司机说,早些年其实是可以进去的,后面国家发展越来越好,便不再让人进去了。
矿区外的停车场,我支楞起装备开始航拍。但是其实,带了三块电池,我只拍完了一块。并不因为没有什么可拍的,相反,我在这里拍出了我的人生照片。

白云鄂博矿坑之一

白云鄂博矿坑之二
照片呀,无法表达我震撼的百分之一。这么说吧,这个照片是我顶着500米的限飞高度拍摄的,只能勉强拍完一个矿坑,而类似的坑至少有两个。其中每一个如蝼蚁的汽车,轮胎都比人高。
可惜的是,我没有缘分亲眼见证了。通过无人机的视角,我也仅仅是窥见其中的惊鸿一瞥。
我想,如果还有机会,来年我还会再来。冬天呢?一片素裹下,肯定更美。
随后我漫无目的地走呀,走呀,走到了城镇的边界,天色也将暗了,我支楞起无人机,又拍了一段人生延时。
返回酒店时爱人已经休息好了。我们小酌清茶。我想,今日我且做了这个小小城镇的山海旅人。

需尽欢。
乘着次日的火车,我们返回包头,再转而搭乘高铁前往呼和浩特。在白云鄂博的记忆好像南柯一梦,但又像刘慈欣所写的“量子玫瑰”一般,时不时在某个魂牵梦萦的夜晚绽放。
呼和浩特的异域风情更甚。黑、灰、绿共同构建了这个城市的主色调。

麦当劳且有蒙古语的麦当劳

清真寺某塔顶

清真大寺的公告板,窥见颇多

关于信仰,关于虔诚

充满异域风情的钟
我在寺里拍呀,拍呀,生怕漏掉一点。这些文字,图案,不,是图腾,我不知道他们还能存留多久,也不知道是否会在某天轰然倒塌,被伟大的红墙砖瓦取而代之。

十字架

清真大寺外景
次日,我们前往大召寺,帮爱人拍了一些着民族服饰的照片。虽然也是十分好看的,但总归景点的感觉浓了一些。

她。

时代的眼泪?

偷闲的小僧


寺庙的鸟总是特别有灵性
我们住在呼市这一晚,酒店十分一般,却也要三百多块钱。后面我们才知道,原来那几天周杰伦过来呼市开演唱会,我们无意中赶上了一波热闹,但是情怀不深,终究没去。
稍晚一些,我们便搭乘高铁前往北京了。列车疾驰,脑子里却浮现出清真大寺公告栏那句话:
顺主归真,敬请阿訇。
北京我已去过许多次,爱人却是第一次来。二环内没有高楼林立,小小地给了她一点首都震撼。
我们从豆汁、焦圈吃开去,一路游到故宫,晚上尽兴时,自然也免不了吃上一顿烤鸭。
而第二日的经历便比较神奇,原本我们只是在南锣鼓巷闲逛,不料下起了大雨,我们一路躲躲闪闪,进入到了开明美术馆避雨。馆内清幽且文静,且只有我们二人,不曾想在这等雨,也度过了极其难忘恬谧的时光。

尹三豆汁,味道正宗,我觉得十分好喝

胡同光景

无障碍似乎可以支撑起残疾人正常生活

一些胡同文化

一些小小的首都震撼

越是中心…胡同越是慢且幽静

免不了一个驴肉火烧,南方几乎没有

开明美术馆,十分难忘
晚一些时,我们前往高铁站准备搭高铁,此行也画上了一个句号。
高铁站中,看着这数十年未见的广告,如梦如幻中,好像又把记忆拉回到小时候那个炎热的午后。那时一家人其乐融融围着不大的电视,看着没有多少营养的广告和电视剧,遥远记忆中一切都那么慢,车呀、马呀、邮件都慢。
真好。

许多年未见的蒂花之秀广告

好吧,用它结尾吧,谁能拒绝一只猫猫呢。
]]>手机运营商提供给用户的最主要的业务我认为有三个:语音、短信和数据。这里我们着重考虑前两种,即语音和短信业务的转发。
至于数据业务:“反正也不干不净,不要也罢。”
不考虑语音转发的情况下,如果只需要做短信转发,方案可选性会更多而且更为简单。在考虑加入语音转发之前,我一直使用的是开源方案 Sms-Forwarder,使用一台闲置安卓手机做短信转发,可靠且稳定。
如果不想使用安卓手机,下文也提供基于PICe模块的方案,因和语音深度集成,放在一起讲。
最初的想法我其实是想提供USB上网卡的方案把SIM卡暴露给系统,再在系统层面进行一些操作。经过一番摸索,我发现现在能用的USB上网卡几乎已经没有了,即使有,USB也仅仅用作取电,不会过多交互数据。更要命的是大部分USB上网卡都是3G卡,随着3G退网这个方案想必无法持久使用。
经过一番摸索我确定用移远的方案,这是一个硬件提供商,提供各种成熟的LTE模块。而底层硬件我在这里用的是光影猫,无它,只因为闲置在工具箱里吃灰,而且正好带了一块LTE模块(购买原意是做4G软路由使用)。
部署完成回过头来看,涉及到的硬件如下:
其中,EM05 安装于光影猫中,前置机、FreePBX 都从 homelab 中分配资源,公网主机也拿现成的直接用即可。但如果自己家里没有对应的基础设施配置,运行这个方案成本或许会比较高。
如果不想用光影猫的方案,通过购置4G模块转接板的MiniPCIe转USB卡座,将模块映射到虚拟机中,并在虚拟机中安装Debian,理论上也可以实现一样的作用。
首先我将光影猫刷为Debian系统并配置静态IP,接入内网,过程不表。值得一提的是机器不带时钟电池,如果没有成功同步时间可能会影响到apt和wget等操作。可以通过 date 命令检查时间并修正。
以下配置过程极大程度地借鉴了这篇文章,如果有不清楚的地方建议回原文查看。
进入系统后应可以识别到移远模块:
root@Photonicat /opt
$ ll /dev/ttyUSB
ttyUSB0 ttyUSB1 ttyUSB2 ttyUSB3
安装 minicom:
apt install minicom
通过以下命令打开与EM05的交互终端:
minicom -D /dev/ttyUSB2
查看版本号:
ATI
重置并重启:
重置模块 at+qprtpara=3
重启 AT+CFUN=1,1
检查SIM卡是否注册成功:
AT+COPS?
+COPS: 0,0,"CHN-UNICOM",7
AT+QNWINFO
+QNWINFO: "FDD LTE","46001","LTE BAND 3",1650
AT+QENG="servingcell"
+QENG: "servingcell","CONNECT","LTE","FDD",460,01
配置VoLTE:
AT+QCFG="ims",1
AT+QMBNCFG="List"
AT+QMBNCFG="AutoSel",0
at+qmbncfg="deactivate"
AT+QMBNCFG="select","ROW_Generic_3GPP"
重启 AT+CFUN=1,1
重启后确认状态:
AT+QCFG="ims"
如果返回的是 +QCFG: "ims",1,1 即为激活,如果是+QCFG: "ims",1,0 说明没有激活
AT+QMBNCFG="List"
如果ROW_Generic_3GPP的第二位和第三位都是1的话,说明dongle目前选择了这个配置 AT+QMBNCFG="List"
+QMBNCFG: "List",0,1,1,"ROW_Generic_3GPP",0x05010824,201806201
+QMBNCFG: "List",1,0,0,"OpenMkt-Commercial-CU",0x05011510,201911151
+QMBNCFG: "List",2,0,0,"OpenMkt-Commercial-CT",0x0501131C,201911141
+QMBNCFG: "List",3,0,0,"Volte_OpenMkt-Commercial-CMCC",0x05012011,201904261
安装Asterisk和依赖:
apt update
apt install asterisk asterisk-dev adb git autoconf automake libsqlite3-dev build-essential libasound2-dev alsa-utils
通过移远提供的项目,可以使得Asterisk可以读取到移远模块。
git clone https://github.com/IchthysMaranatha/asterisk-chan-quectel
cd asterisk-chan-quectel
./bootstrap
./configure --with-astversion=16
make
make install
编译成功后,将uac/quectel.conf复制到/etc/asterisk里。并通过systemctl restart asterisk重启asterisk。
输入asterisk -rvvv进入asterisk的cli界面并输入quectel show devices即可看到识别到的dongle:
$ asterisk -rvvv
Asterisk 16.28.0~dfsg-0+deb10u4, Copyright (C) 1999 - 2021, Sangoma Technologies Corporation and others.
Created by Mark Spencer <[email protected]>
Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.
This is free software, with components licensed under the GNU General Public
License version 2 and other licenses; you are welcome to redistribute it under
certain conditions. Type 'core show license' for details.
=========================================================================
Connected to Asterisk 16.28.0~dfsg-0+deb10u4 currently running on Photonicat (pid = 1545)
Photonicat*CLI> quectel show devices
ID Group State RSSI Mode Submode Provider Name Model Firmware IMEI IMSI Number
quectel0 0 Free 27 0 0 CHN-UNICOM EM05 EM05CEFCR06A04M1G 867144039000000 460018660000000 Unknown
Photonicat*CLI>
直接照抄没啥问题:
$ cat /etc/asterisk/extensions.conf
[incoming-mobile]
;exten => _.,1,Dial(SIP/70/100)
;same => n,Hangup()
exten => sms,1,Verbose(Incoming SMS from ${CALLERID(num)} ${BASE64_DECODE(${SMS_BASE64})})
;store
;exten => sms,n,System(echo '${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} - ${QUECTELNAME} - ${CALLERID(num)}: ${BASE64_DECODE(${SMS_BASE64})}' >> /var/log/asterisk/sms.txt)
exten => sms,n,System(echo '${BASE64_DECODE(${SMS_BASE64})} - ${CALLERID(num)} - ${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)}' >> /var/log/asterisk/sms.txt)
;for tg bot use
;exten => sms,n,System(echo '${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} - ${QUECTELNAME} - ${CALLERID(num)}\n${BASE64_DECODE(${SMS_BASE64})}' >> /var/log/asterisk/unread_sms/${STRFTIME(${EPOCH},,%Y%m%d%H%M%S)}-${CALLERID(num)}.txt)
exten => sms,n,Hangup()
exten => ussd,1,Verbose(Incoming USSD: ${BASE64_DECODE(${USSD_BASE64})})
exten => ussd,n,System(echo '${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} - ${QUECTELNAME}: ${BASE64_DECODE(${USSD_BASE64})}' >> /var/log/asterisk/ussd.txt)
exten => ussd,n,Hangup()
;exten => _.,1,Set(CALLERID(name)="")
exten => _.,1,Dial(SIP/70/100)
exten => s,n,Hangup()
[Outbound-1001]
exten => _.,1,Dial(Quectel/quectel0/${EXTEN})
same => n,Hangup()
炫一段GPT的解释:
这个Asterisk的dialplan包括两个上下文:[incoming-mobile]和[Outbound-1001],实现了以下功能: [incoming-mobile] 上下文 处理呼入短信: 当收到短信时,该上下文会捕捉到sms扩展。 第一个优先级(1)使用Verbose应用程序将来自特定电话号码的短信内容解码并记录在日志中。 第二个优先级(n)使用System应用程序将短信内容、发件人电话号码以及当前时间追加到/var/log/asterisk/sms.txt文件中。 第三个优先级(n)挂断通话。 处理呼入USSD: 当收到USSD消息时,该上下文会捕捉到ussd扩展。 第一个优先级(1)使用Verbose应用程序将USSD消息内容解码并记录在日志中。 第二个优先级(n)使用System应用程序将USSD消息内容和发送时间追加到/var/log/asterisk/ussd.txt文件中。 第三个优先级(n)挂断通话。 处理其他呼入事件: 对于任何其他事件,该上下文捕捉到特殊的_扩展名。 第一个优先级(1)使用Dial应用程序从SIP设备70拨打到SIP设备100。 第二个优先级(s)挂断通话。 [Outbound-1001] 上下文 处理外拨电话: 该上下文捕捉到特殊的_扩展名。 第一个优先级(1)使用Dial应用程序从Quectel设备quectel0拨打到指定的电话号码。 第二个优先级(n)挂断通话。
建议重启服务器而不是重启Asterisk,确定没有问题后测试短信:
asterisk -rx 'quectel sms quectel0 10010 "cxll"'
确定 /var/log/asterisk/sms.txt 可以收到即可。
这里我用现成的shell脚本,丢给GPT直接做成一个python脚本,调用企业微信应用接口来发送短信。
脚本配置好ID、secret后摆到以下文件: /opt/send_notification.py
#!/usr/bin/env python3
import requests
import json
from pathlib import Path
import time
def get_json_value(json_obj, key, default):
return json_obj.get(key, default)
# AgentId, 2 for HA, 3 for Aduit
AGID = "CHANGEME"
# AppSecret
ASECRET = "CHANGE-ME"
# CorpID
CORPID = "CHANGEME"
sms_file = Path('/var/log/asterisk/sms.txt')
def send_notification(new_content):
print("Sending notification...")
# Sending Context
CONTEXT = f"{new_content}"
# Obtain Token Json Array
response = requests.get(f'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={CORPID}&corpsecret={ASECRET}', timeout=5)
JSON = response.json()
TOKEN = get_json_value(JSON, 'access_token', None).strip('"')
data = {
"touser": "@all",
"msgtype": "text",
"agentid": AGID,
"text": {"content": CONTEXT}
}
result = requests.post(f'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={TOKEN}',
headers={"Content-Type": "application/json"},
data=json.dumps(data), timeout=5)
if result.status_code == 200:
print("Notification sent successfully.")
else:
print(f"Failed to send notification. Status code: {result.status_code}. Response: {result.text}")
def watch_sms_file(file_path):
last_position = file_path.stat().st_size if file_path.exists() else 0 # Ignore the existing content by starting from the end of the file
print("Starting to watch the sms file...")
send_notification("SMS Monitoring System Started")
while True:
file_path.touch(exist_ok=True) # Ensure the sms file exists
with open(file_path, 'r') as sms_file:
sms_file.seek(last_position)
new_content = sms_file.read()
if new_content:
print(f"New content detected: {new_content.strip()}")
send_notification(new_content)
last_position = sms_file.tell()
time.sleep(1) # Time interval to check the file again
if __name__ == "__main__":
watch_sms_file(sms_file)
新建一个服务:
$ systemctl cat sms-notify.service
# /etc/systemd/system/sms-notify.service
[Unit]
Description=SMS-Wechat Notification
After=network-online.target
[Service]
Type=simple
User=root
Restart=on-failure
RestartSec=15
ExecStart=/usr/bin/python3 /opt/send_notification.py
[Install]
WantedBy=multi-user.target
随后启用服务、开启自启动:
systemctl daemon-reload
systemctl enable --now sms-notify.service
一切正常的话你会收到一条提醒:
SMS Monitoring System Started
至此,短信部分配置完成。
下载安装 FreePBX,过程不表。值得一提的是如果Chrome没有弹出ISO下载,尝试用Edge。
完成初始设定后,添加两个分机号,一个用于接收端使用,一个用于测试手机调试使用。这里分别用801和802.
Applications – Extensions – Add Extension
注意Secret,这个相当于密码,后面在手机端注册需要用到。

其他保持默认设置即可。
这里我们希望和光影猫的Asterisk建立trunk,而且不希望通过导入CID。如果自动导入CID,所有呼入来电均会变为移远的端口名。
进入FreePBX的SSH,增加以下配置:
[root@freepbx ~]# cat /etc/asterisk/extensions_custom.conf
[from-trunk-no-cidname]
exten => _X.,1,Set(CALLERID(name)="")
exten => _X.,n,Goto(from-trunk,${EXTEN},1)
[root@freepbx ~]#
回到网页端,点击 Connectivity – Trunks – Add Trunk
按如下设置


注意这里的Authentication被关闭,SIP Server为光影猫的地址,端口可以在这个文件查到:
$ cat /etc/asterisk/sip.conf
[general]
context=sip-default
udpbindaddr=0.0.0.0:46000
tcpbindaddr=0.0.0.0:47000
tlsbindaddr=0.0.0.0:5063
tlscipher=ALL
tlsclientmethod=tlsv1
accept_outofcall_message=yes
allow=!all,slin,ulaw,alaw
allowguest=no
allowtransfer=yes
alwaysauthreject=yes
.....
这里的 Context 我们设置为 from-trunk-no-cidname ,会进入上面的设置清洗掉CID。
在 Connectivity – Outbound Routes设置呼出路由:


在Dial Patterns里我设置了两种外呼格式,分别是1开头的号码和9开头的号码。这样在呼出手机等1开头的号码时自动走移远模块。如果呼叫固话,则先打9再跟固话即可。(和之前一些酒店的设置一样)
在 Connectivity – Inbound Routes设置呼入路由:

进入Settings – Asterisk SIP Settings,给RTP更改端口范围:

这里还把RTP Timeout改成3,原因是在外网呼叫电话时,挂断信号无法正常被转发,这里将设置为3秒无语音包后挂断电话。
进入 chan_pjsip页,开启TCP监听:

同时在下面把外网域名和外网IP写上。
保存,应用更改,重启服务器。
我发现有很多变更无法通过Web重启生效。任何涉及Asterisk的变更我都建议直接重启FreePBX服务器。
此时基本配置就已经完成了,手机下载Zoiper,新建一个SIP Account,Domain写FreePBX的IP,Username写801,密码为上面设置的Secret。另一台则按照802的配置,两边都注册成功后,你就可以通过801,802这两个号码互相拨打电话了。
值得一提的是目前几款VoIP软件,比如Zoiper,SessionTalk的实现逻辑差异很大。在内网使用时没有太大区别,但我们还需要保证软件没有打开在前台时能正常接到推送通知(这里以iPhone为例),Zoiper为订阅制软件,SessionTalk为买断制,但Zoiper可以将RTP语音流一并进行转发,这能修正很多因NAT无法转发SIP而导致的问题。
我经过长时间测试,在下文提到的FRP方案中,没有找到一个不修改FRP源码就可以成功转发语音流的方案。所以最终使用Zoiper的订阅服务进行操作。
进入前置机配置frpc的转发如下:
[freepbx_sip_port_udp_10000]
type = udp
remote_port = 10000
local_port = 10000
local_ip = 192.168.1.241
[freepbx_sip_port_udp_10001]
type = udp
remote_port = 10001
local_port = 10001
local_ip = 192.168.1.241
[freepbx_sip_port_udp_10002]
type = udp
remote_port = 10002
local_port = 10002
local_ip = 192.168.1.241
[freepbx_sip_port_tcp]
type = tcp
remote_port = 5060
local_port = 5060
local_ip = 192.168.1.241
local_ip为FreePBX的IP地址。重启frpc服务后,如果一切正常,你就可以从公网的5060端口注册到你的PBX服务器了。
如果你尝试拨打电话,正常来说是可以接通但是没有语音的。这里进入Zoiper的Settings,进入Incoming Calls,将Proxy Protocols选择为 SIP + RTP,再尝试拨打电话,就可以了。
最后,完成一切配置后,重启光影猫和FreePBX服务器,确保所有组件在重启后都能正常启动。
如果有监控系统的话,同时对光影猫的46000端口和FreePBX的5060端口做一个监听和告警,以免服务宕机影响使用:

这个配置繁琐,且要求已有的基础设施众多,可能不适合大部分人使用。但是读到这里的人,想必也无需多说什么了。
祝你我向上走,有一份热,发一分光。
使用EC20模块配合asterisk及freepbx实现短信转发和网络电话
从0到1打造自己的VOIP网络电话系统(基于FreePBX)
]]>我并不是第一次开始反思这个问题。自从毕业之后,我也算是踩着互联网的东风,工资一路水涨船高,但我非但存不到钱,反而似乎工资越高,困扰越多。
我并不是没有经历过糟糕的财务阶段。毕业前后,微薄的收入加上不时大额的花销,经过数年累积,也欠下了一笔不大不小的外债。后面时常反思那段时间,在财务状况不甚理想时,只要支出大于收入这个循环便永远无法打破。哪怕有意控制支出,也起不到任何作用。
用那时候兴起的话术来说,那是一个“消费主义”盛行的年代。人们追求更好的生活品质、更高的生活质量似乎是天经地义的事情。一切欲望都是那么正当,一切束缚欲望的行为都是逆着时代洪流的倒退。我似乎是从那时候开始意识到,人的欲望远不止无穷无尽。在欲望面前,吞噬理性,构造需求,一切都是顺理成章。
也是巧,周期律巧妙地给经济画上了休止符。人们终于幡然醒悟。而我在消费主义无尽的精神内耗中也终于摆脱开来,读一本书并不比拥有一件昂贵的玩具带给我的欢愉更少。
时隔许久,我回顾每一个消费的欲望时,他们都像一片片叶子,引向同一个树干,有着同一个树根。写这篇文章时我并没有大彻大悟,或许将来某一天我会知道,有哪些叶子我应该任由它们发黄枯萎也不可惜。
]]>为什么是400字,相对于推特140字,400字我有更多但恰如其分的词句来进行概括和总结,但我也认为我已经失去了撰写800字长文的能力,亦或者为了写出更长的字句,我需要更有仪式感地进行准备,而我并不想如此。
过去这段时间我几乎无时不刻在挣扎、焦虑和无序中度过。新冠带来的影响远超其本身的病理性。去年十一月的事件,让我坚定了要出国的决心。
“贪安稳就没有自由。”
然而时代的洪流之下没有人能独善其身。今年几乎没有合适的岗位开出,无论是在哪个我心仪的国家。这种焦虑蔓延至今年六月,我的职能经理正式宣告退休,而接替他的岗位的是一位很卷的香港经理。说实话经过短时间的磨合,我是有一些失望的。
与此同时伴随着年龄而来的生育压力每日俱增,我也不确定,我的犹豫不决最终是否会由我的伴侣买单,而我并不想如此。
今年注定是变化的一年。祝福自己,断舍离,拥抱变化吧。
]]>我决定前往香港开立我的银行账户。
开一个香港的银行账户并不难,甚至在现时比在大陆开银行账户更简单。但是这也并不是一项十分随意就能做成的事情,我前期大致做了如下准备。
D-X代表出发日前X日应开始准备
首先你要有一张通行证并且去自助机获得签注。十分简单不多表。
值得一提的是由于各种原因目前并不是所有自助机都已经开放,务必做好攻略再去。
查攻略得知有很多银行一开始会要求存一万块港币进去,这里我在中行预约外币提取,拿了两万块现金。你也可以去到香港再在ATM取人民币,但应注意手续费。
如果你的身份证地址不是你的收信地址,务必获取一份地址证明文件。最简单的方法通常是要求信用卡机构邮寄。最好可以盖章。
如果你的运气不好,或者Banker对你的KYC比较严谨,很可能会被要求出示你的股票投资记录,或者可用于投资的资金。 这里建议提前把资金归结一下,表现出投资的诚意。非必选项。
经过一番查攻略我决定开立以下几家账户:
Q: 为什么需要这么多个账户?
A: 目前看来每家账户都有各自的优势。如果只开一家并且不频繁使用的话会被转化为不动户,不再去香港激活很可能用不了。多开几家至少可以资金互转避免这个问题。同时现在有很多银行不再提供Visa/MC卡,只提供银联卡,在支付时容易受到限制。
选定这几家银行的大致原因,中银香港目前国内出金没有手续费(暂时),HSBC全球同名账户转账管理都很方便,永隆普遍比较容易开,工银亚洲出金也是比较方便。ZA作为新兴的互联网银行也值得持有,App看起来很好用,但资金不可以转回大陆。Livi和ZA性质差不多,这两家互联网银行开户都用不了五分钟,我都是在各家银行等待叫号的时候顺便开好了的。
确定好这几家银行后,我在网上预约了工银亚洲尖沙咀东分行的开户,在永隆银行的App填好开户资料,并在HSBC预约开立HSBC One账户。但是由于没有接到HSBC的电话,我并没有成功预约,而临近出发日期,我只能选择walk-in。
随后就是要确定行程以及路线计划。由于最近大陆前往香港开户的人很多,我并不想去网红点凑热闹。我决定选择一个远离高铁和地铁的地方,最终选定出了高铁直接打车去上环。由于工银亚洲已经预约在尖沙咀片区,我也不想过去那边白跑一趟,每家银行我都选择了两个分行,其中一个作为Plan B。
上环区:
中国银行 上环皇后大道西
永隆 永隆银行西区分行
(Backout) 中国银行(香港)般含道分行
hsbc 般咸道分行
===========
尖沙咀区:
(Backout) 永隆银行 尖沙咀加拿分道4號
(Backout) 汇丰尖沙咀分行
工行 中国工商银行尖沙咀东分行
以上是我确定的行程,两个片区的分行走路不超过10分钟都能去到,计划当时按照这个顺序走应该没有问题,但实际上依然有一些出入。
每个银行必问的第一个问题都是:你为什么想开立我们的账户呢?
我的回答是:理财和炒港股。
这个问题其实很难回答好。这直接决定了开立账户的权限是普通的储蓄户口,还是带有理财户口,以及是否有港股、美股的权限。于此同时,理财经理也可能会就你的回答继续进行KYC,或是查看你的股票交易记录,或是进行资产核验。但无论如何,目前来说港股似乎是一个比较合理且低成本的回答,相较于保单缴费或是储蓄、旅游等答案比较容易被银行接受。
做好了以上的思想建设,就可以准备出发啦。
总结一下我带了什么东西过去:
于是我定了最早一班的高铁,随着信号变成CSL和3,我到了香港西九龙。 我原本打算打一个Uber去我的第一个网点,然而出了站后我的路痴属性急性发作,根本找不到Uber可以去哪里搭乘,幸亏换了400散钱,我决定排队搭的士过去上环。
由于过了一条隧道,收了过路费,打车费比国内来说其实挺贵,15分钟的路程花了差不多170 HKD,但是这基本也是本行程唯一的支出了。上了车我才发现,出租车司机也开始在用滴滴接单了……早知如此!
因为路痴发作耽误了一些时间,到达皇后大道西的中银时已经8点50分,但因为不是热门网点,银行也还没有开门,门口也没有人在等。开门进去后直接拿号,和大堂经理说想开立户口,大堂经理确认了我有带一万HKD后便同意了,并没有多问。随后要求下载中行的两个App,与经理沟通后可以在等待过程中预录入信息。
等的过程中随手把ZA的申请也提交了。
接待我的理财经理小姐姐非常好人,我把文件给她之后更多的是闲聊和等待。期间会让我阅读费率标准,应该是SOP的一部分。
账户开好后小姐姐就开始指导我设置BOCHK的App,但是在激活过程中有一步要拍照身份证,经过了多次尝试都不能正常识别,于是小姐姐打电话给support,经过大概15分钟的等待后台帮我跳过了这个认证过程,得以继续设置。在这个网点开户是没有当场下卡的,储蓄卡会通过平信邮寄到预留的通信地址,所以正确的地址证明非常重要。
办理结束后其实并没有要求我存入一万块钱,当时排队的人很多,我确实也没有过去存。但是在下午的时候我还是找了个少人的ATM机存进去了,万一人家有考核呢。
由于我到了的时候没有直接过去办理而是拿了个号,其实第一个进去可以直接坐过去不用拿号的。等了前面的人办理完到我的时候大概是9点30分,到我办理完大概是10点30分。排除掉身份验证导致的问题,大概是40分钟办结。
出来的时候大概是十点半钟,恰好狂风大作,我觉得我过去永隆的路上大概率会下雨,而与此同时又刚好看见有一家HSBC,于是就进去问一下是否可以开户。这家门店并不在计划内,本着问一下又不会掉块肉的理念我去到了汇丰银行德辅道西分行。
这家银行的开户并没有想象中的顺利,进门后和大堂经理表明来意,当问到我为什么要开户时我回答炒港股,而大堂经理回怼我说:现在大陆也可以做港股交易啊!这种情况只能急中生智,还是出金到这边做比较方便,基金什么的大陆也只有QDII可以选择云云。随后大堂经理问大概有多少资金打算用于投资,做过攻略的我就知道开始要验资了,我便自觉打开银行账户余额给她看,她拿了资料进后台说问下能不能开户,过了几分钟后告诉我可以,稳了!
随后领进一个小隔间,并没有要排队。汇丰的开户问了很多问题,甚至包括我是否买了房,房子总价多少,按揭金额多少,投资股票的偏好等等。因为汇丰的系统是英文的,开户的Banker还帮忙把地址翻译成拼音。因为我的开户理由是理财,也叫了一个理财的同事过来和我聊了很久,主要推荐了一款储蓄型保险,我表现得很感兴趣,即兴问了很多问题。(实际上并不感兴趣)
汇丰是我唯一一家当场拿到卡的银行,开好户后拿到卡,出门在ATM就可以改密码使用了。配发的卡也是银联卡,但可以在App上申请邮寄MC卡。据说是平邮寄到,我很担心拼音地址能否顺利收到,但是也有人说可以补发并要求发DHL。
HSBC出来后已经不下雨了,时间也来到了中午十二点半。我按计划去到永隆西区分行,但当时只有一个柜员,告诉我人手不够,暂时没有办法开户,建议我下午三点后再来,或换一家分行。由此触发了Backout Plan。上环区的事情也做得差不多了,稍微逛了下,我搭地铁前往尖沙咀。
我此时其实有些犹豫,永隆和工银只是作为一个备用,不开也没有什么损失。相反永隆还有日均1万的要求,否则有账户管理费。到尖沙咀永隆后也已经差不多一点半,我拿了个号,心里想着如果永隆开完过了两点就不去工银了。
然而,永隆这个网点并没有直接开户,相当于只是把资料收上去后等待审核,而且也没有下卡。由于没有太多的KYC反而不到五分钟就做完了,但是目前为止永隆的账户并没有开立出来,还在审核阶段。如果后面不能开卡的话我并不打算留住。
没想到永隆这么快,出来后也不到两点,我便过去预约的工银亚洲网点准备开户。等待时间很久,差不多到三点才有理财经理出来接待,感觉整个节奏都很慢。但因为我也已经有足够账户可用,并不介意,想着三点如果没有人接待我就回去算了。
接待的是一个男的经理,也是例行问了开户理由,其他并没有多问,感觉有些冷淡。 等他弄好资料后他便说要去审核,更多的是在等待。
开好户后,他也只是稍微指导了下手机App的使用,但是最后有帮我在ATM机存钱进去,还留了他的微信给我,说有理财的问题可以问他,原来不是冷淡,只是慢热型~
工银开完户也是没有当场给卡,平邮寄送。出来后已经四点半了,ZA和Livi的开户也已经成功,银行们基本也准备下班了。
总的来说香港的开户并不像小某书上那样玄乎,各种排队,各种被拒。只要你的开户理由是真实的,合规的,基于投资的,KYC并不会有太多问题。避开所谓的网红开户点,其实大家都只是一家正经银行。
]]>购房并不是哪天脑子一热的决定。我和她现在在国内一线城市租房居住,工作稳定,生活和睦。然而,年龄所带来的生育焦虑(主要是对她,她比我大好几岁)让我们萌生了在这个城市生根的想法。“萌生”这个词或许并不准确,毕竟是经历过无数次大吵小吵后,从某方面来说,是生活推着我们做出这个迫不得已的决定。
在第N次争吵后,我决定主动做出改变。她渴望在大城市有一个家,而我深切地明白,如此沉重的资产购置,尚且不在我们目前的负担能力范围之内。理性地看待这个事情,我们并没有足够的资本作为首付资金(房款30%),据我所知,差之甚远。但是每次精疲力竭的争吵,毫无目的的争吵,毫无结果的争吵,只是不断在消耗两个人的耐性,这个值在这一天达到阈值——我们开始质疑是否和对方在一起是一个正确的决定。
我必须主动进行风险管理,在这个阶段,筹集资金不重要,重要的是愤怒管理。
我决定用Notion来进行资源汇总,同时用看板来跟进每次讨论的要点。
争吵没有要点,讨论有。
定期的讨论,我认为可以舒缓她的焦虑情绪,并把这件事情朝着两个人可以接受的timeline推进。
至于是否延误,这不是这个spirit讨论的重点。

综合考虑购房与生育的时间节点,我拟定了一个时间点,使得这个时间点在人类幼崽项目交付时,购房计划也恰到好处地完成。

在这里,我使用看板来进行备孕、孕期以及生育后的事项管理。通过定义不同的优先级,我们在有限的周末时间中有轻重缓急地推进整个备孕进程。
这里我并没有用看板来做购房事件的跟踪,原因是我们定义了一个周会议,在会议中我们会review上次会议的未决事项,以及列明本次所作的决定,以及直到下次会议时需要跟进的事项。

这被定义成一个模板,每次的会议纪要都是统一的格式。
这个例会+看板的机制很快取得成效,她不再无缘无故焦虑。直到后期,她一但开始焦虑已经学会主动翻阅Notion中的记录。很明显,这也有助于她将那些一闪而过的焦虑思想从井井有条的日志中逐一化解。
在例会中,我们大致确定了购房的方向:二手房,离地铁站近,可负担的首付。而首付始终是一个迈不过去的坎,很快我们就需要联系双方家庭以获取资金支持。

这不是一个小数目,而且这是一个漫长的过程。但是得益于每周的跟进,我们还是提前完成了80%的资金归结计划,相对于原计划这提前了差不多8个月,是一个非常可喜的成绩。
很可惜的是,我们两个人有着相当可观的公积金余额,但却无法用于首付资金。奉劝看到文章的各位,如果急需筹集首付资金,务必自己不要缴存过多的公积金比例。对于我们,这部分公积金余额我们打算用于装修。
在中介的不断推荐与我们每周不停地地毯式筛选后,很快我们选择到了第一套兴趣点房源——更确切地说,可能是我更感兴趣。它有着很明显的问题也有着很明显的优势,我会在后面列明。
在表明对这套房子感兴趣后,我们进行了三次上门看房,一次在白天,一次在晚上,一次在雨天。为了获取到更真实客观的数据,我们也咨询了保安,包括下雨是否积水,对应的学位评价如何,是否容易停车等一系列能想到的,十分具体的问题。在最后一次上门时,我还带上了iPad pro并用canvas对房屋进行3D建模,建立的模型很粗糙,但仍有一定的参考意义。(我不确定iPad非pro版本是否会得到更差的数据,因为缺乏激光雷达的支持。)
在与她评估这套房子的过程中,她没有表现出十分的兴趣,但也不表现出抵制。这让我造成了我们可以往下走的错觉。
我尝试做了一个Pros&Cons来协助我们理清,我们是否真的适合购买这套房子。
现在回看,不得不说,Pros确实比较牵强,Cons比较硬而且无解居多。

在结婚两周年纪念日中,我们做了Go/No-Go的决定。在晚餐中,我们商定,中介同业主沟通,同意降价到某个价格,我们就支付定金。
Go decision is made.
很快我们联系了中介,中介联系了业主,不到5分钟,我们被告知,定价被接受。
这让我觉得不可思议,要价要高了。
很快她联系了家人,说明了购置计划准备实施,而我联系好银行房贷部准备按揭,也把理财款悉数赎回。
在她与一个朋友的沟通中,那位朋友对她做出了极大的影响。否认这种老房子具备投资价值,并一再建议她投资核心地带的新房源。很快,她被说动了,这套房子对她来说不再是刚需,有没有房子在小孩子出生之前就绪也不再是刚需。
需求变了,一切都变了。
她不再认同我们做的这个决定,并坚持撤销交易。
很快,我们执行了回退计划。幸运的是,定金还没有交,除了劳民,尚未伤财。
作为一次失败的交易,我也逐渐反思。这套房子,她的朋友提到的问题并不是不存在,但在当时的界定条件下(有限首付资金、有限筹款时间、特点区块房源)这是我们不得不做的唯一选择。正如我和她说的,买这套房子不是一个好的选择,推迟做决定也不是一个好的选择。
鉴于她已经更改了限定条件,不再执着于房子要在生小孩之前就绪,目前我们有更充足的时间进行评估以及更长的时间筹集首付资金。更重要的是,No-Go的决定是她做的,她也考虑清楚明白这个决定的后果,她将不会无缘由地对购房产生焦虑。
虽然目前为止需要焦虑的事情很多,但我在通知中介撤销交易时确实感觉如释重负。如此看来,这套房子在更充裕的限定条件下,确实不适合我们。
]]>FRP(Github)正好可以满足我的要求。不仅可以实现内网业务的映射,也可以实现服务器端业务的映射,以使得在内网安全稳定地访问公网敏感业务(例如SSH)。同时还支持注册为systemd服务,稳定性更好。
在使用FRP之前我们要搞清楚自己希望通过FRP实现什么。
以一个最简单的拓扑为例:
我有一台公网服务器,我希望内网的业务暴露在公网。业务类型可能是HTTP(s)类业务或者是TCP类业务。我也希望我能够隐藏公网的一些服务(比如SSH),通过FRP自带的STCP功能将流量加密地发回到我的客户端,并通过客户端的特定端口来进行访问。
以我的实际拓扑为例:
我有一台公网服务器用作堡垒机,作为FRP的服务器。我有另一台公网服务器承载业务,我希望通过堡垒机管理这台生产服务器的SSH。
我使用FRP的STCP功能加密SSH流量发到堡垒机上,并在公有云后端的防火墙对SSH端口进行封禁。
我有一台内网服务器,上面是一个ESXi主机,其中我建立了一台Edge Server作为边界节点,Edge上运行了FRP客户端,把公网服务器的SSH流量转发到自己的某个端口。同时客户端还把内网中的其他业务暴露到FRP堡垒机。
最后基于安全配置,我在堡垒机(FRP服务器)上也开启了FRP的客户端,将堡垒机的SSH也转发到自身,并在内网的Edge服务器访问。同时关闭堡垒机侧防火墙公网对SSH端口的访问。
下载回来frp组件,frps是服务器组件,frpc是客户端组件。
针对默认配置,我们做了一些修改。
# [common] is integral section [common] # A literal address or host name for IPv6 must be enclosed # in square brackets, as in "[::1]:80", "[ipv6-host]:http" or "[ipv6-host%zone]:80" bind_addr = 0.0.0.0 # 这里绑定管理端口 bind_port = 7000 # udp port to help make udp hole to penetrate nat # 绑定UDP端口 bind_udp_port = 7001 # udp port used for kcp protocol, it can be same with 'bind_port' # if not set, kcp is disabled in frps # 绑定KCP端口 kcp_bind_port = 7000 # specify which address proxy will listen for, default value is same with bind_addr # proxy_bind_addr = 127.0.0.1 # if you want to support virtual host, you must set the http port for listening (optional) # Note: http port and https port can be same with bind_port # 进行HTTP(s)流量转发时需要用到这个端口,流量会被打到这个端口上并用二级域名做区分。 vhost_http_port = 6666 vhost_https_port = 8888 # response header timeout(seconds) for vhost http server, default is 60s # vhost_http_timeout = 60 # set dashboard_addr and dashboard_port to view dashboard of frps # dashboard_addr's default value is same with bind_addr # dashboard is available only if dashboard_port is set # Web管理面板,非必须。0.0.0.0指这个面板可以被任意访问,127.0.0.1指这个面板只能被自己访问。 dashboard_addr = 127.0.0.1 dashboard_port = 6688 # dashboard user and passwd for basic auth protect, if not set, both default value is admin # 管理面板的用户名、密码 dashboard_user = username dashboard_pwd = password # dashboard assets directory(only for debug mode) # assets_dir = ./static # console or real logFile path like ./frps.log log_file = ./frps.log # trace, debug, info, warn, error log_level = warn log_max_days = 3 # disable log colors when log_file is console, default is false disable_log_color = false # auth token # 指定和客户端的通讯密码 token = password # heartbeat configure, it's not recommended to modify the default value # the default value of heartbeat_timeout is 90 # heartbeat_timeout = 90 # only allow frpc to bind ports you list, if you set nothing, there won't be any limit # 允许TCP、UDP流量打到FRP服务器特定的端口组 allow_ports = 6101-6200 # pool_count in each proxy will change to max_pool_count if they exceed the maximum value max_pool_count = 50 # max ports can be used for each client, default value is 0 means no limit max_ports_per_client = 0 # if subdomain_host is not empty, you can set subdomain when type is http or https in frpc's configure file # when subdomain is test, the host used by routing is test.frps.com # 用作HTTP流量转发的子域名 subdomain_host = frp.iam.lc # if tcp stream multiplexing is used, default is true tcp_mux = true # custom 404 page for HTTP requests # custom_404_page = /path/to/404.html
将这个配置文件保存到 /etc/frp/frps.ini
然后我们开始写systemd脚本:
# /etc/systemd/system/frps.service [Unit] Description=Frp Server Service After=network.target [Service] Type=simple User=root Restart=always RestartSec=5s ExecStart=/usr/bin/frps -c /etc/frp/frps.ini [Install] WantedBy=multi-user.target
配置好自启动,服务器端就配置完成了。
关于端口放通,我们需要放通以下端口:
7000 TCP+UDP 主通信端口
7001 UDP UDP通信端口
6666 TCP HTTP虚拟主机端口
8888 TCP HTTPS虚拟主机端口
6101-6200 TCP+UDP 客户端业务注册端口
6688 TCP 管理面板端口
基于七层HTTP的业务映射,FRP允许我们使用 A.frp.iam.lc 子域名来进行访问。A可以自行定义。而基于TCP的端口业务映射,我们也通常给予一个域名 frp.iam.lc 来进行访问。
我们需要添加以下两条A记录到你的DNS解析:
*.frp.iam.lc -> 堡垒机IP
frp.iam.lc -> 堡垒机IP
至此,服务器侧配置完成。
在内网的linux服务器安装好frpc客户端,我们开始写配置文件:
/etc/frp/frpc.ini
[common] server_addr = 1.2.3.4 # 服务器IP server_port = 7000 token = password pool_count = 4 protocol = kcp
以上是每个客户端的公共配置部分。这将作为基础连接参数,被下面要添加的各种服务引用。
下面我们要把内网的NAS存储转发到公网,内网的NAS IP是192.168.1.230,我们打算转发到公网的6101端口,并使用TCP映射。
[local_nas] type = tcp remote_port = 6101 local_port = 443 local_ip = 192.168.1.230
这样我们就把NAS的HTTPS端口映射到了frp.iam.lc:6101上。
而我们转发的实际上是HTTPS流量,我们还需要在证书扩展背景名称中将frp.iam.lc加进来。(仅适用于自签名证书)
在生产服务器,我们部署frpc客户端后,进行配置。
首先添加公共模块,如上所示。
然后我们添加SSH的STCP转发:
[stcp_ssh] # 对应Server Name,在客户端用到 type = stcp sk = your-secret # 密钥 local_ip = 127.0.0.1 # 转发本地流量,也可以转发其他主机流量 local_port = 22 # 转发端口,这里以SSH为例 tls_enable = true # tls加密 use_compression = true # 启用压缩
值得一提的是,STCP流量并不要求我们指定端口。
回到内网的Edge服务器,我们添加以下配置:
[stcp_ssh_client] type = stcp role = visitor server_name = stcp_ssh sk = your-secret bind_addr = 0.0.0.0 # 如果绑定0.0.0.0则会被内网所有主机访问。如果只想被自己访问则绑定127.0.0.1 bind_port = 6101 # 这是绑定到Edge的端口,和服务器无关。 use_encryption = true use_compression = true
至此,我们可以通过frp在内网通过堡垒机加密流量,ssh到公网服务器了。
假设Edge Server的IP是192.168.1.250,我们可以通过以下命令连接到公网服务器SSH:
ssh -p6101 192.168.1.250
非常简单,类似服务器配置:
# /etc/systemd/system/frpc.service [Unit] Description=Frp Client Service After=network.target [Service] Type=simple User=root Restart=on-failure RestartSec=5s ExecStart=/usr/bin/frpc -c /etc/frp/frpc.ini ExecReload=/usr/bin/frpc reload -c /etc/frp/frpc.ini [Install] WantedBy=multi-user.target
systemctl daemon-reload systemctl enable --now frpc
]]>
目前,网络上关于SSH密钥对生成教程,出于方便,一般都使用默认的rsa加密。这里,我们更加讲究地使用ecdsa来进行密钥对的生成。
ssh-keygen -t ecdsa -b 521
请注意,这里我们十分讲究地使用了521位加密(不是512!)。
生成完毕后,如果你在这里没有输入私钥的密码,我们会生成一个不带密码的私钥。这个不带密码的私钥虽然不安全,但是有其使用场景。例如。。。好吧我想不出来。那这里我们对他进行加密。
cp id_ecdsa id_ecdsa_encrypted ssh-keygen -p -f id_ecdsa_encrypted
这样我们就可以生成一个新的私钥文件“id_ecdsa_encrypted”了。
非常简单,一行命令搞定上传。
ssh-copy-id -i id_ecdsa.pub {username}@{hostname}
此时,目标服务器如果还启用了密码验证的话,则需要输入密码。如果启用了证书,则必须确保证书在生成密钥的机器上可以正常被读到。(例如已经安装了rsa密钥,要更新ecdsa密钥)
在没有加固之前,相信你每次登陆ssh都有几万次login failed的提示。
这里我们对 /etc/ssh/sshd_config 文件进行一些关键字段的修改,来实现加固
Port 1234 StrictModes yes #请确保~/.ssh/及其文件的文件权限正确 MaxAuthTries 3 MaxSessions 3 PubkeyAuthentication yes PasswordAuthentication no X11Forwarding no PermitRootLogin no #请确保有低权限账号创建,能正常被ssh登陆,并加入了sudoer豪华午餐
大部分人应该一眼都能明白改的啥吧,不解释了。
]]>
购买的是13寸带指纹的版本,CPU是7200U,内存8G,显卡MX150,硬盘是256G的NVME,自己花了一千多大洋追加了一块1T的SATA。
性能来说,够用。日常办公使用,几十个Chrome标签页加一堆乱七八糟进程,从不关机,最多休眠。一个月重启一次很正常。
续航分两段说,一开始是很给力的,大概能重度用一个上午。使用一年左右后急速衰减,大概还剩20%的电量,会直接关机。售后死不认账,遂自己掏钱换电池,之后恢复。
主要说说两段维修历史。
第一段大概在到手后三个月,发现风扇在怠速模式下会有比较大的噪音,所以尝试自己拆机清灰,不过因为自己的疏忽,带电清灰,导致开机无显示。报售后,更换主板。
这段更换很不愉快的一点是备件准备花了很长时间,前前后后等主板备件大概等了一个月,严重严重影响工作。
虽说直接原因是自己拆机导致的问题,但是有果必有因,如果风扇没有问题我也不会拆不是。
更要命的是发现更换过来主板没写SN号,直接让工程师写。之后发现充电明显比之前慢了很多,之前大概30分钟能充一大半,更换主板后充满要差不多3个小时。。。
之后又提了几次400,死无对证,没有任何办法。
查看AIDA64,可以发现充电功率大概在12-20W,充电头也不烫,之前是很烫的。多次插拔可以协商出30-40的功率,且要满足温度很低才行。(北京冬天丢室外充电)
第二段就是上面提到的电池更换。我自己使用是大概20%剩余的时候自动关机,结果在售后点他们说复现不出,急着出差,叫他们先下单定备件,如果复现不了我自己掏钱换。最终结果当然是复现不了了。
不过好在不贵,记得一百来块钱。比市面上其他厂商的便宜多了。而且旧电池还送回给你,这个我觉得很赞。(毕竟我旧电池还有80%电能用的)。
后期更换电池、更换充电头,都没有办法解决充电速率的问题。我估计再换就得换整机了。当然下一家也不会选小米了。
目前使用来说还有一个问题是屏幕有带状偏色,在深色背景下特别严重。应该是屏幕工艺问题导致的瑕疵。考虑到过保了,去撕逼也只能自己掏钱,算了。
]]>