ORAY 민들레 원격 네트워킹을 사용하여 Raspberry Pi 원격 SSH 액세스 실현

요약

  1. 나는 회사와 집에서 디버깅하고 개발할 수 있기를 바라며 Raspberry Pi 4B로 시작했습니다.
  2. 회사와 가정에는 공용 네트워크 IP가 없으므로 (통신 방식을 사용하는 것이 좋습니다) 공용 네트워크에서 Raspberry Pi에 액세스할 방법이 없습니다.
  3. 가상 머신 개발 환경의 준비가 너무 번거롭고 닭을 죽이는 것은 큰 망치입니다.
  4. 나는 매일 보드를 가지고 앞뒤로 달리고 싶지 않습니다.

필요

  1. 전원 켜짐
  2. 부팅 후 인터넷 연결 여부 감지(스크립트 자동 실행)
  3. 네트워크 연결이 성공적인지 확인한 후 Dandelion에 로그인합니다(자동으로 스크립트 실행).
  4. 네트워킹 후 LAN IP 주소로 메일을 보냅니다(파이썬 파일 자동 실행).
  5. Dandelion을 통한 원격 네트워킹을 통해 Raspberry Pi에 액세스합니다.

준비(중요)

  1. Raspberry Pi가 ssh를 엽니다.
  2. WiFi 자동 연결 설정;
  3. Dandelion을 설치하고 자동 로그인을 설정하십시오.
  4. 스마트 소켓.

공식적으로 시작

1단계: Dandelion 서비스를 시작하는 스크립트 만들기

pgyvpnservice.sh 스크립트를 생성하여 /home/pi/Desktop 디렉터리에서 Dandelion 서비스를 시작합니다.

#!/bin/sh
#/etc/init.d/pgyvpnservice.sh
### BEGIN INIT INFO
# Provides:testboot
# Required-Start:$remote_fs $syslog
# Required-Stop:$remote_fs $syslog
# Default-Start:2 3 4 5
# Default-Stop:0 1 6
# Short-Description: testboot
# Description: This service is used to start my applaction
### END INIT INFO
case "$1" in
  start)
    echo "启动蒲公英异地组网"
    su root -c "pgyvpn"	# 以root模式执行pgyvpn指令打开蒲公英
  ;;
  stop)
    echo "执行完毕"
  ;;
esac

2단계: 네트워크 감지 스크립트 만들기

/etc/init.d 디렉터리에 네트워크 감지 스크립트 network_test.sh를 만듭니다.

#!/bin/bash
#检测网络链接&&ftp上传数据
declare -i n=0	#创建变量n并声明为数值
while [ $n -ne 1 ]	#判断n是否不等于1
do
	ret_code=`curl -I -s --connect-timeout 5 baidu.com -w %{
    
    http_code} | tail -n1`	#网络值
	if [ "$ret_code" = "200" ]; then
		nohup /home/pi/Desktop/pgyvpnservice.sh &	#网络连接成功后需要启动的程序脚本,即pgyvpnservice.sh
		n=1;
	else
		n=0; #失败等待
	fi
done

3단계: 시작 항목 구성

네트워크 연결을 감지하기 위해 부팅을 구현하고 네트워크 연결이 정상인 후 Dandelion을 실행하십시오.

  1. rc.local 파일을 편집합니다.
sudo nano /etc/rc.local
  1. exit0 전에 입력:
nohup  /etc/init.d/network_test.sh &	#后台启动网络检测脚本

4단계: LAN IP 주소를 지정된 사서함으로 자동 전송

목적 :

  • 할당된 IP 주소를 보기 위해 라우터에 로그인할 수 없을 때 Raspberry Pi의 위치를 ​​파악합니다.
  • 이메일을 받은 후 Raspberry Pi가 인터넷에 연결되고 Dandelion이 성공적으로 열렸음을 확인할 수 있습니다. 이를 통해 공용 네트워크 액세스를 실현할 수 있습니다(이 단계는 Dandelion 콘솔 또는 클라이언트를 통해서도 수행할 수 있지만 캐시로 인한 문제는 및 기타 문제는 이메일을 통해 효과적으로 피할 수 있습니다).
  1. Raspberry Pi 주소를 가져오고 이메일을 보내려면 ip_address.py를 작성하십시오.
# -*- coding: utf-8 -*-
from multiprocessing import connection
import socket
import smtplib
import time
import socket

# 分割线内部分为网络检测,如在树莓派设置网络检测脚本,本部分可省略
# ------------------------------------------------------------------
# 测试网络连接情况
def isNetOK(testserver):
    s=socket.socket()
    s.settimeout(3)
    try:
        status = s.connect_ex(testserver)
        if status == 0:
            s.close()
            return True
        else:
            return False
    except Exception as e:
        return False
# 测试百度是否可以访问
def isNetChainOK(testserver=('www.baidu.com',443)):
    isOK = isNetOK(testserver)
    return isOK
if __name__ == '__main__':
    connection_attempt=True
    while connection_attempt:
        chinanet = isNetChainOK()
        if chinanet==True:
            break
# ------------------------------------------------------------------

# 邮件发送方邮箱地址
MAIL_USER = ''
# MAIL_PASS要使用授权码而非密码
MAIL_PASS = ''
# 邮箱stmp服务器地址
SMTP_SERVER = ''
SMTP_PORT = 25
# 邮件接收方邮箱地址
recipient1=''
# 邮件主题
subject1 = 'ip_address'
#获取IP地址
def get_host_ip():
    try:
        s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
        s.connect(('8.8.8.8',80))
        ip = s.getsockname()[0]
    finally:
        s.close()
    return ip

def send_mail(input_text):
    text = input_text
    
    smtpserver = smtplib.SMTP(SMTP_SERVER,SMTP_PORT)
    smtpserver.ehlo()
    smtpserver.starttls()
    smtpserver.ehlo
    smtpserver.login(MAIL_USER,MAIL_PASS)
    
    header = 'To:'+recipient1+'\n'+'From:'+MAIL_USER
    header = header + '\n' +'Subject:' + subject1 +'\n'
    timeStr = time.strftime(' %Y_%m_%d %H:%M:%S',time.localtime(time.time()))
    msg = header +'\n'+text+'\n'+timeStr+'\n\n'
    smtpserver.sendmail(MAIL_USER,recipient1,msg)
    smtpserver.close()

time.sleep(10)
send_mail(get_host_ip())
  1. ip_address.py를 /home/pi/Desktop에 복사합니다.
  2. 부팅 시 시작되도록 ip_address.py를 설정합니다.
# 编辑rc.local文件
sudo nano /etc/rc.local
# 在exit0前、nohup  /etc/init.d/network_test.sh &后输入:
sudo python /home/pi/Desktop/ip_address.py

5단계: 이메일을 통해 Raspberry Pi에 명령 전송 실현

  1. command_trans.py는 비상 시 이메일을 통해 Raspberry Pi 터미널과 제한된 임시 통신을 수행할 수 있습니다.
import os
import datetime
from calendar import TextCalendar
from cgitb import text
from operator import truediv
import poplib
import base64
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
from time import sleep
import smtplib
from email import encoders
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from unittest import result

def get_email_content():
	useraccount = ''
	password = ''

	# 邮件服务器地址,以下为网易邮箱
	pop3_server = 'pop.163.com'

	# 开始连接到服务器
	server = poplib.POP3(pop3_server)

	# 打开或者关闭调试信息,为打开,会在控制台打印客户端与服务器的交互信息
	server.set_debuglevel(0)

	# 打印POP3服务器的欢迎文字,验证是否正确连接到了邮件服务器
	# print(server.getwelcome().decode('utf8'))

	# 开始进行身份验证
	server.user(useraccount)
	server.pass_(password)

	# 返回邮件总数目和占用服务器的空间大小(字节数), 通过stat()方法即可
	email_num, email_size = server.stat()
	# print("消息的数量:{0}, 消息的总大小:{1}".format(email_num, email_size))

	# 使用list()返回所有邮件的编号,默认为字节类型的串
	rsp, msg_list, rsp_siz = server.list()
	# print("服务器的响应: {0},\n消息列表: {1},\n返回消息的大小: {2}".format(rsp, msg_list, rsp_siz))

	# print('邮件总数:{}'.format(len(msg_list)))

	# 获取最新的一封邮件
	total_mail_numbers = len(msg_list)
	rsp, msglines, msgsiz = server.retr(total_mail_numbers)
	# print("服务器的响应: {0},\n原始邮件内容: {1},\n该封邮件所占字节大小: {2}".format(rsp, msglines, msgsiz))

	msg_content = b'\r\n'.join(msglines).decode('gbk')
	# 邮件信息(未解码)
	msg = Parser().parsestr(text=msg_content)
	# print('解码后的邮件信息:\n{}'.format(msg))
	# 关闭与服务器的连接,释放资源
	server.close()

	return msg

# 用来解析邮件主题 
def parser_subject(msg):
	subject = msg['Subject']
	value, charset = decode_header(subject)[0]
	if charset:
		value = value.decode(charset)
	# print('邮件主题:{0}'.format(value))
	return value

# 用来解析邮件来源 
def parser_address(msg):
	hdr, addr = parseaddr(msg['From'])
	# name 发送人邮箱名称, addr 发送人邮箱地址
	name, charset = decode_header(hdr)[0]
	if charset:
		name = name.decode(charset)
	# print('发送人邮箱地址: {0}'.format(addr))
	return addr

def parser_content(msg):
	content = msg.get_payload()
	# 文本信息
	content_charset = content[0].get_content_charset() # 获取编码格式
	text = content[0].as_string().split('base64')[-1]
	text_content = base64.b64decode(text).decode(content_charset) # base64解码
 
	# 添加了HTML代码的信息
	# content_charset = content[1].get_content_charset()
	# text = content[1].as_string().split('base64')[-1]
	# html_content = base64.b64decode(text).decode(content_charset)
 
	# print('文本信息: {0}'.format(text_content))
	return text_content

def send_email(command, execution_feedback):
	# sender是邮件发送人邮箱,pw是服务器授权码,mail_host是服务器地址
	sender = ''
	pw = ''
	mail_host = ''
	# receivers是邮件接收人,用列表保存,可以添加多个
	receivers = ['']

	# 设置email信息
	msg = MIMEMultipart()
	time_stamp = '{0:%Y-%m-%d-%H-%M}'.format(datetime.datetime.now())
	# 邮件主题
	msg['Subject'] = command + ' -- Execution result -- '+time_stamp
	# 发送方信息
	msg['From'] = sender
	# 邮件正文是MIMEText:
	msg_content = execution_feedback
	msg.attach(MIMEText(msg_content, 'plain', 'utf-8'))

	# 登录并发送邮件
	try:
		#QQsmtp服务器的端口号为465或994
		s = smtplib.SMTP_SSL(mail_host, 465)
		s.set_debuglevel(1)
		s.login(sender,pw)
		#给receivers列表中的联系人逐个发送邮件
		for item in receivers:
			msg['To'] = to = item
			s.sendmail(sender,to,msg.as_string())
			print('Success!')
		s.quit()
		# print ("All emails have been sent over!")
	except smtplib.SMTPException as e:
		print ("Falied,%s",e)

if __name__ == '__main__':
	# 返回解码的邮件详情
	msg = get_email_content()
	# 解析邮件主题
	value=parser_subject(msg)
	# 解析发件人详情
	addr=parser_address(msg)
	# 解析内容
	text_content=parser_content(msg)
	# 保证每次开机读取邮件时不会被已有邮件干扰
	command_line=text_content
	send_email('设备已开机,网络连接正常,已准备好通过邮件接收指令。', '最新一封邮件内容:'+text_content)
	while True:
		# 返回解码的邮件详情
		msg = get_email_content()
		# 解析邮件主题
		value=parser_subject(msg)
		# 解析发件人详情
		addr=parser_address(msg)
		# 解析内容
		text_content=parser_content(msg)
		if text_content!=command_line:
			command_line=text_content
			statement_execution = os.popen(command_line.replace('\n', '').replace('\r', ''))
			feedback_line = statement_execution.read()
			send_email(command_line,feedback_line)
		else:
			pass
		# 每间隔5分钟进行一次邮件收发
		sleep(300)
  1. command_trans.py를 /home/pi/Desktop에 복사합니다.
  2. 부팅 시 시작하도록 command_trans.py를 설정합니다.
# 编辑rc.local文件
sudo nano /etc/rc.local
# 在exit0前、sudo python /home/pi/Desktop/ip_address.py &后输入:
sudo python /home/pi/Desktop/command_trans.py

6단계: 전원을 켜고 시작한 다음 Dandelion 서비스가 온라인 상태가 될 때까지 기다립니다.

스마트 소켓을 사용하여 전원을 원격으로 제어하고, 전원을 켠 후 네트워크 상황에 따라 일정 시간 동안 대기한 후 LAN IP 주소 이메일을 받거나(권장) 라즈베리 파이가 로그인되어 있고 ping이 가능한지 확인합니다. Dandelion 콘솔/클라이언트, 즉 Dandelion에서 할당한 IP 주소를 통해 공용 네트워크를 통해 액세스할 수 있습니다.

지침

  1. 사전에 준비 항목의 모든 작업을 완료하십시오. Dandelion은 자동 로그인이 실행될 수 있는지 확인해야 합니다. 그렇지 않으면 스크립트가 서비스를 시작할 수 없습니다.
  2. rc.local 파일에서 시작 항목의 순서에 주의하십시오 순서가 잘못되면 시작 항목이 정상적으로 시작되지 않을 수 있습니다.
  3. 첨가되는.

추천

출처blog.csdn.net/m0_37728676/article/details/108513568