windows/linux远程开关机原理及实现

远程开关机原理

一、远程开机

1.局域网唤醒

硬件需求:

a.首先要有主板支持。现在,新一代的主板大都支持网络唤醒功能,而且在主板上都有一个三脚插座,它一般在PCI插槽附近,旁边标注“WOL”。

b.其次必须要有网卡支持。这类网卡在主板上比一般的网卡多了一个三脚插座,并且通常还附带一条专用的三芯连接线,该线是用来连接主板和网卡之间的三脚插座。

c.最后还必须要使用ATX电源,而且其+5V Standby电流必须比较大,根据Intel的建议,它需要在600mA以上。该电流的大小可以从电源外部标识中的+5VSB栏里查到。

需要说明的是,某些主板上已经集成了具有网络唤醒功能的网卡,所以也就没有什么三脚插座,更不需要专用的三芯连线。

如果电脑支持这些硬件需求,需要在BIOS里将wake on lan选项打开。

唤醒原理:

在基于TCP/IP协议的网络中,计算机处于关机状态时 我们不可能有计算机的IP地址,唯一能识别计算机身份的只有其所带网卡的物理地址(mac),每块网卡的mac地址都是唯一的。要远程唤醒某台计算机,必须事先知道其mac地址,然后通过magic picket(AMD公司开发的)标准生成对应的远程唤醒数据包,再利用UDP协议进行广播,向网络发送该数据包。

控制机通过发送一个幻数据包(magic packet),幻数据包是一个广播帧,包含目标计算机的mac地址。由于mac地址的唯一性,使数据包可以在网络中被唯一的识别。

幻数据包通常使用无连接协议,例如UDP,发送端口通常为7或9,没有限制。

大多数网卡都支持在超低功耗下监听特定报文。如果设备网卡接收到一个与自己 MAC 地址相同的幻数据包,则网卡会向计算机的电源或主板发出信号以唤醒计算机。MAC地址通过命令ifconfig查看。大部分的幻数据包在数据链路层(OSI模型第2层)上发送,当发送时,使用广播地址广播到给定的网络上,不使用IP地址(OSI模型第3层)。当然这是绝大部分情况,幻数据包也可以使用特定的 IP 地址进行发送。

幻数据包最简单的构成是6字节的255(FF FF FF FF FF FF FF),紧接着为目标计算机的48位MAC地址,重复16次,数据包共计102字节。有时数据包内还会紧接着4-6字节的密码信息。这个帧片段可以包含在任何协议中,最常见的是包含在 UDP 中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JJZjwd0e-1623999655774)(C:\Users\nova003804\AppData\Roaming\Typora\typora-user-images\image-20210616104958389.png)]

例如 MAC 地址为 11 22 33 44 55 66 的目标计算机,幻数据包的格式为:

FFFFFFFFFFFF 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 [ABABABABABAB(这里为6个字节的密码)]

注意:传送的时候必须封包成二进制格式才可以传送

幻数据包起作用的限制条件:

  1. 需要知道目标计算机 MAC 地址
  2. 不提供送达确认
  3. 可能无法在局域网之外工作
  4. 需要硬件进行支持(网卡支持网络唤醒)

注:通过ethtool eno1(网卡名,通过ifconfig命令查看)查看wake on lan是否开启,g为开启,d为关闭

如果关闭,关机之前必须通过命令ethtool -s eno1 wol g打开,否则无法远程开机

实现代码:

package main

import (
	"bytes"
	"encoding/hex"
	"flag"
	"fmt"
	"net"
	"strings"
)

var help = "hello,please input params like wol -mac XX:XX:XX:XX:XX:XX"
func main()  {
	mac := flag.String("mac","",help)
	flag.Parse()

	if len(*mac) == 0{
		fmt.Printf("%s\n",help)
		return
	}

	hw := strings.Replace(strings.Replace(*mac,":","",-1),"-","",-1)

	if len(hw) != 12{
		fmt.Printf("MAC:[%s] 输入不正确。\n",*mac)
		return
	}

	macHex,err := hex.DecodeString(hw)
	if err != nil{fmt.Printf("MAC:[%s] 输入不正确。\n",*mac)
		return
	}

	var bcast = []byte{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}
	var buff bytes.Buffer

	buff.Write(bcast)

	for i := 0; i < 16; i++{
		buff.Write(macHex)
	}

	mp := buff.Bytes()

	if len(mp) != 102{
		fmt.Printf("MAC:[%s] 输入不正确。\n",*mac)
		return
	}

	sendMagicPacket(mp)
}

func sendMagicPacket(mp []byte){
	//sender := net.UDPAddr{}
	target := net.UDPAddr{
		IP:   net.IPv4bcast,
	}

	conn,err := net.DialUDP("udp",nil,&target)
	if err != nil{
		fmt.Printf("创建UDP错误:%v", err)
		return
	}

	defer conn.Close()

	_,err = conn.Write(mp)
	if err != nil{
		fmt.Printf("魔包发送失败[%s]", err)
	}else{
		fmt.Printf("魔包发送成功")
	}

}

2.远程跨网段唤醒

远程过路由开机无法进行广播,局域网唤醒手段无法使用。

3.开机后启动程序

linux

在控制机上,通过xshell等软件控制

windows

方案1:被控主机应打开远程功能,控制机启动被控机之后,通过远程桌面连接被控机,进行相关操作

方案2:设置想启动的程序为开机启动项

方案3:在远程开机代码中直接添加开机启动项(目前还未找到实现方式)

二、远程关机

1.windows关机linux

前提:同一网段内,两台机器可ping通,被关机的机器需开启远程功能。

远程ssh登陆,发送poweroff即可关机:输入ssh 用户名@服务器IP命令之后,再输入密码,即可远程登陆linux服务器。

连接成功的前提是,linux需开启ssh服务。yum install ssh,/etc/init.d/sshd start

2.windows关机windows

前提:

  1. 同一网段内,两台机器可ping通

  2. 需在在运行中输入gpredit.msc打开策略编辑器,计算机配置->windows设置->安全设置->本地策略->用户权限分配,双击打开“从远程系统强制关机”,并添加Guest用户

  3. 在用户权限分配中选择“拒绝从网络访问这台计算机”,并删除Guest用户

  4. 右键我的电脑->管理。依次选择系统工具->本地用户和组->用户,选择Guest双击打开,将“账户已禁用”前边的√去掉

  5. 完成以上操作后,若还不能远程关机。

    依次打开:

    控制面板 -> Windows Defender 防火墙 -> 选择 启用或关闭 Windows Defender 防火墙。

    将 Windows Defender 防火墙 全部关闭。

关机命令:shutdown -s -m\\xx.xx.xx.xx(IP)

3.远程关机原理

控制面板 -> Windows Defender 防火墙 -> 选择 启用或关闭 Windows Defender 防火墙。

    将 Windows Defender 防火墙 全部关闭。

关机命令:shutdown -s -m\\xx.xx.xx.xx(IP)

3.远程关机原理

shutdown的命令格式中,-m这个参数后边可以指定要关闭的计算机,省略的话默认对本机操作

在windows默认的安全策略中,只有管理员组的用户才有权从远端关闭计算机。一般情况下,从局域网你内其他电脑访问该计算机时,只有Guest用户权限。只要在计算机中赋予Guset用户远程关机的权限即可。

你可能感兴趣的:(windows/linux远程开关机原理及实现)