树莓派通过邮件上报实时IP,随时随地远程登录树莓派

树莓派接上键鼠和显示器就是一台普通的Linux的主机了,这样没什么好玩的。我的想法是只接网线和电源,将它作为一台永久运行的个人服务器,随时随地可以远程登录它,在上面跑耗时的爬虫代码等任务。

除了一台装好Linux系统(Raspbian)的树莓派,一根路由器给的网线,合适的放置环境,我们还需要做软件方面的配置。主要是如何从外网ssh登录到树莓派,昨天晚上写了个脚本解决了这个问题,这里分享一下。

电信分给用户的IP是动态的,我使用的一般是2天变化一次,重启路由器的话立即改变。ssh需要的就是ip和用户名,所以只要解决了ip的问题,就可以做到随时登录了。

1.路由器静态分配内网IP

路由器在内网分配的ip也是动态的,以我的为例,是tplink的路由器,内网的ip两个小时换一次,电脑重启立即改变。

解决方案比较简单。

  1. 打开路由器的管理页面(通常是192.168.1.1,不同型号也可能不同)。
  2. 在DHCP服务中将地址池设置为192.168.1.100-200,这样动态分配的ip会在这个范围。
  3. 设置静态分配。添加一个静态分配的规则,添加树莓派的MAC地址和静态分配的IP(要在局域网的网段,通常是192.168.1.XXX,而且不要在Step2设置的地址池范围内),我使用的是192.168.1.20.

JINGTAIFENPEI

如果不知道自己的MAC地址,可以在打开DHCP服务的时候查看一下。或者在树莓派中用ifconfig命令查看HWaddr

到此为止,任何时候只要你连接了这个路由器,就可以使用192.169.1.22登陆到树莓派系统了(通常情况下,路由器的设置都需要重启生效)。

2.外网IP和端口映射到内网

如果想要从外网登陆的话,还需要做一步映射。因为路由器分出了很多ip,如果外网访问某一端口的话,到底是访问了哪一个ip呢?

在路由器的「转发规则」页面添加一个对22端口(这个就是ssh端口)的转发,到192.168.1.20(你在上一节设置的IP)上。

zhuanfaguize

设置成功,你可以在 http://www.ip138.com/ 查看一下自己当前的ip是多少,然后尝试使用这个ip ssh登陆,正常情况下,是可以登陆的。

3.解决外网IP变化的方法

外网的IP一旦改变,原来的你记住的ip就失效了,解决这个问题,我用的方案是:树莓派每一个小时检查自己的公网ip,如果改变,就向我的邮箱发送一封邮件报告自己的最新ip。

原理是使用Linux的crontab添加定时任务,任务就是一个脚本,这个脚本来做check ip和发送邮件的功能。

操作步骤:

  1. 在树莓派上登录Root账户(sudo -s),因为这个程序要放在/root/rootcrons下而且添加为root的例行程序。
  2. 执行git clone https://github.com/laixintao/Report-IP-hourly.git /root/rootcrons/下载脚本代码(如果放在别的目录下,要注意调整后面的步骤相应的路径)。
  3. vi reportip.py设置邮件信息,修改代码的e-mail config部分:
    • smtpserver:你的SMTP服务器
    • username:你登陆SMTP的用户名
    • password:密码
    • sender:发送人,注意要和SMTP登录的账户对应,通常都是一个一个邮箱账户。
    • receiver:收信人列表
    • subject:邮件主题

    具体的修改信息,在代码中有详细的注释。

  4. 执行crontab /root/rootcrons/rootcron,将rootcroon的任务添加到crontab列表中。
  5. 重启crontab,使配置立即生效。/etc/init.d/cron restart

这时整个定时检查ip并发送邮件的功能已经实现了,下一节是解释代码和更高级的配置,如果没有兴趣可以跳过,去读一下「特别注意」(我惨痛的教训)。

如何得到树莓派的内网ip?

开一个socket,然后用python直接获得此socket的名字。代码像这样:

3.5添加开机启动

通过使用了一段时候之后,我发现,如果ip变化了,而树莓派启动的时间不是在整点的话,你只能等到下一个整点才能收到邮件了。所以这里我们再加一步,将脚本添加至开机启动里面。

这一步很简单,只要 vim /etc/rc.local ,然后添加下面一句话就可以了。

4.代码原理

最新版本的代码请看这里:https://github.com/laixintao/Report-IP-hourly

脚本会先检查网络是否连通,连通才会有后续的步骤。方法是访问百度是否正常返回结果(百度的主要功能是检查自己在不在线,不是搜索引擎)。

如果联通,则尝试获得公网ip,使用一个lastip.txt来保存ip地址,每次检查的结果和这个ip对比,如果相同,则不发送邮件。

那么如何获得公网ip呢?我的方法是去访问一个测试ip的网站,得到的html中用正则表达式去找ip。脚本中提供了三个网址,如果失败或者访问超时(默认20s),则尝试下一个。如果不能满足需要大家可以添加更多。

有朋友指出,我这里的地址已经失效了,并提供了下面两个可以获取ip的地址。

  • http://www.ip138.com/ip2city.asp
  • http://ipv4.icanhazip.com/
  • https://httpbin.org/ip  (这也比较稳定哦)

运行结果像下面这样:

reportip

详细的代码和注释请见github吧。

关于crontab

crontab filename是将任务添加到定时计划中,如果有需要可以更改rootcron的配置来控制脚本的执行频率。rootcron中的代码像下面这样:

  • 第1列分钟1~59
  • 第2列小时1~23(0表示子夜)
  • 第3列日1~31
  • 第4列月1~12
  • 第5列星期0~6(0表示星期天)
  • 第6列要运行的命令

例如,数字表示第x分钟或者小时来执行,*表示每分钟/小时等执行。详细介绍见文末参考。

5.特别注意

  1. 树莓派放置环境,注意温度不能太高。
  2. 如果1 2小节设置完毕之后测试失败,试一下重启路由器,路由器的设置一般都是在重启之后生效的。不同的路由器相应地菜单和设置方法可能是不一样的,有一些甚至没有提供转发功能。
  3. 不要使用常用邮箱给树莓派做发送用,这样不安全,最好申请一个邮箱专门给树莓派发送报告用。
  4. 添加到crontab之前最好手动执行一下(python reportip.py)来看一下代码是否能够正常执行,可以的话再添加到crontab。
  5. 如果代码有授权失败异常(503),先不要怀疑是自己的配置出错了,去邮件提供商,看一下设置里面的「客户端SMTP」是否允许了(别问我怎么知道的,申请了三个邮箱才反应过来啊!)。
  6. 收信箱请设置一个规则,例如标题带[RPI]的放到[RPI]的放到一个RPI文件夹,不提示。这样自己就不会被打扰,邮件也不会被扔到垃圾箱了。
  7. 特别重要!crontab执行脚本的时候运行环境是和我们直接在shell执行不一样的!!!所以crontab文件中的命令全部写绝对路径,例如/usr/bin/python /root/rootcrons/reportip.py这样。脚本中所有用到的配置都要写绝对路径,例如file文件存放的目录(两个小时才找到这个bug啊衰!手动执行正常,crontab就是不正常!)。

6.推荐使用

  • TP-link路由器:提供了映射服务,我的路由器支持花生壳动态解析,挺好用的。
  • Secure Shell for Chrome:配色好看,而且使用这个,无论你用Windows,mac,linux还是什么系统,只要有Chrome,就可以随时登陆ssh。

SCURESHELL-FOR-CHROME

JUICESSH

  • what for ios?:我没有iPhone,iPhone用户自求多福吧 :)。

7.其他获得解决动态变化的IP的方案

这些方法我也考虑过,有兴趣的朋友可以实现以下:

  1. 发送邮件的方式改为用网页公开。写一个html网页,然后用ftp上传到自己的服务器,这样每次想要看最新的ip的话只要打开这个网页看一下就行了。缺点:总觉得树莓派不安全,放这里ftp密码有点不放心。
  2. 有一种叫做动态解析的东西。缺点:花钱。

8.树莓派做服务器的缺点

树莓派做到7×24运行,不知道靠不靠谱,我是个稳重的人,所以给树莓派贴了两片散热铜片还装了个风扇。只是…………这破烂玩意太吵了,这么点个风扇比机箱还吵。

安卓使用app无法ssh登陆,估计是22端口被屏蔽了,因为我用vpn访问是正常的。

9.参考资料

最后,如果你遇到了本文没有解决的问题,可以留言或电邮,会在6个小时之内得到回复。



树莓派通过邮件上报实时IP,随时随地远程登录树莓派”已经有50条评论

  1. Serverauditor for IOS;铜片够了;22端口是被屏蔽的。noip是有免费动态域名解析,但就是会时不时往你注册邮箱发个广告让你买服务。

  2. 很感谢你的教程!但是由于年代久远,reportip.py中获取IP地址的网站该更新啦,这两个都是可以用的“http://www.ip138.com/ip2city.asp”“http://ipv4.icanhazip.com/”

  3. 楼主,请教一下这是怎么回事
    root@raspberrypi:~/rootcrons# python reportip.py
    Network is Ready!
    IP information from http://ipv4.icanhazip.com/
    IP changed.
    Traceback (most recent call last):
    File “reportip.py”, line 108, in
    sendEmail(ipaddr)
    File “reportip.py”, line 39, in sendEmail
    smtp.login(username, password)
    File “/usr/lib/python2.7/smtplib.py”, line 622, in login
    raise SMTPAuthenticationError(code, resp)
    smtplib.SMTPAuthenticationError: (535, ‘5.7.8 authentication failed’)

    • 你好,从traceback来看,ip获取正常,但是发送邮件的时候失败了,你应该检查一下你发送邮件的部分,比如邮箱的用户名密码,端口是否都设置正确了。

      如果使用的是163的邮箱,要注意163邮箱的密码不是你的登录密码,而是另一个特定的用于客户端登录的密码。

    • 在sendEmail的函数里,msgRoot.attach后面加上
      smtp = smtplib.SMTP()
      smtp.connect(smtpserver,587) #587是gmail的smtp的端口。
      smtp.ehlo()
      smtp.starttls()
      smtp.ehlo()

    • hi,我尝试了几次代码,发现ip不变的时候是不会发送邮件的,所以我怀疑你的ip一直在变化。不知道发送到你的邮件的ip是否都是一样的?

      你可以在树莓派上clone下来这个代码,然后重复执行几次试一下(python reportip.py),如果发现每次执行ip都变了,说明代码部分没问题,要么是你使用的监测ip的网址不准,要么的确是你的ip变化频率很高。

      • 就是因为发送过来的邮件都显示一样的ip,所以我需要反馈这个问题啊。
        发过来的邮件都是给出这个地址114.232.21.44
        然后我检查了lastip.txt,里面是两个ip地址,一个就是上面一个,另一个是我所在的内网地址10.0.0.6
        直接python运行提示是
        network is ready
        ip information from http://members.3322.org/dydns/getip
        ip changed
        successfully sent the e-mail
        很奇怪ip明明没变哪来的ip changed.

    • 这说明ip变了啊,你再运行几次,每一次都会变吗?

      另外他说successfully sent the e-mail,你应该会收到邮件的,你看下邮件内容里面的ip变了吗?

      • 反复运行多少次,都提示ip changed,邮件已经几十封了,每封邮件的地址都一毛一样
        我不会用命令行拷贝,scp命令不会用的。
        lastip.txt文件存在的,没问题,里面有两个ip,一个公网的一个内网的,也没问题

        • 会不会是文件编码的问题。你比较一下两次命令生成的文件是不是不一样。内容一样但是提示不一样的话很可能是文件写入的过程有问题

          • ip终于变了,还是反复发邮件
            文件编码怎么看?不明白
            放弃在树莓派上用这个了,内网还有路由器什么的麻烦死了,如果是在vps上用的话感觉会很方便。
            还是感谢你的代码

    • 兄弟,我试了你的这个网址,也是 Ip not change啊,我录了一段实验过程你可以看看:https://asciinema.org/a/onknbfPeoIvUs7SEk9zbpH1N5,可能需要翻墙看。我怀疑是你的环境问题了…… 你检查一下lastip.txt文件的位置,是不是找不到这个文件来比较啊?

  4. outlook 邮箱好像没办法配置呀?

    pop
    服务器名称: outlook.office365.com
    端口: 995
    加密方法: TLS
    smtp
    服务器名称: smtp.office365.com
    端口: 587
    加密方法: STARTTLS

  5. 問題都解決了~謝謝樓主
    不過,我想請教一下,如果要在電腦上測試,要如何解決
    “server_hostname cannot be an empty string or start with a leading dot.”的問題呢?

  6. 请问为什么每次都是获取到内网ip,发邮件是内网ip,不是公网的
    Network is Ready!
    IP information from http://www.whereismyip.com/
    Fail to get the Network ip.
    Get the LAN ip.
    192.168.2.3 192.168.2.3
    IP changed. New ip: 192.168.2.3 192.168.2.3

  7. 博主你好!我成功的测试了,但是我想在发送邮箱的时候,不想发送内网的ip,代码需要修改那一块?可以修改发送邮箱的的正文内容吗?想添加几个字进去!

  8. 嗯,可以了,有什么办法可以让发送的邮件内容进行换行,因为发送的邮件内容公网ip和内网ip的字符间距挨得太密集了,看起来怪怪的,想分别换行显示公网和内网ip,但是我查了资料,网上说发送邮件的内容含有html格式的话,需要加\n\r,我加了,不起作用,想问问你什么有解决的办法吗?

回复 xiang wang 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注