Created
September 26, 2024 14:35
-
-
Save maple3142/03668d75c5c319244b474e881c16835a to your computer and use it in GitHub Desktop.
wake on lan go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto/ecdsa" | |
"crypto/elliptic" | |
"crypto/rand" | |
"crypto/tls" | |
"crypto/x509" | |
"crypto/x509/pkix" | |
"encoding/pem" | |
"fmt" | |
"log" | |
"math/big" | |
"net" | |
"net/http" | |
"os" | |
"strconv" | |
"time" | |
) | |
const ( | |
defaultTargetMAC = "11:22:33:44:55:66" | |
defaultListenPort = 12345 | |
) | |
var targetMAC net.HardwareAddr | |
var listenPort int | |
func generateSelfSignedCert() (tls.Certificate, error) { | |
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) | |
if err != nil { | |
return tls.Certificate{}, err | |
} | |
notBefore := time.Now() | |
notAfter := notBefore.Add(365 * 24 * time.Hour) | |
serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) | |
if err != nil { | |
return tls.Certificate{}, err | |
} | |
template := x509.Certificate{ | |
SerialNumber: serialNumber, | |
Subject: pkix.Name{ | |
Organization: []string{"maple3142"}, | |
}, | |
NotBefore: notBefore, | |
NotAfter: notAfter, | |
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageContentCommitment, | |
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, | |
BasicConstraintsValid: true, | |
} | |
template.DNSNames = []string{"localhost"} | |
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) | |
if err != nil { | |
return tls.Certificate{}, err | |
} | |
privBytes, err := x509.MarshalECPrivateKey(priv) | |
if err != nil { | |
return tls.Certificate{}, err | |
} | |
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}) | |
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: privBytes}) | |
return tls.X509KeyPair(certPEM, keyPEM) | |
} | |
func wol(mac net.HardwareAddr) { | |
magicPacket := make([]byte, 6+16*len(mac)) | |
for i := 0; i < 6; i++ { | |
magicPacket[i] = 0xFF | |
} | |
for i := 0; i < 16; i++ { | |
copy(magicPacket[6+i*len(mac):], mac) | |
} | |
conn, err := net.Dial("udp", "255.255.255.255:9") | |
if err != nil { | |
log.Println("Failed to send magic packet:", err) | |
return | |
} | |
defer conn.Close() | |
conn.Write(magicPacket) | |
log.Println("Magic packet sent") | |
} | |
func handleWOL(w http.ResponseWriter, r *http.Request) { | |
if r.URL.Path == "/wol" { | |
if r.Method == http.MethodPost { | |
wol(targetMAC) | |
fmt.Fprintln(w, "Magic packet sent") | |
} else { | |
w.Header().Set("Content-Type", "text/html") | |
fmt.Fprintln(w, `<form method="post"><button>Wake up</button></form>`) | |
} | |
} else { | |
http.NotFound(w, r) | |
} | |
} | |
func main() { | |
// read mac address and port from environment variables | |
var err error | |
targetMACStr := os.Getenv("TARGET_MAC") | |
if targetMACStr != "" { | |
targetMAC, err = net.ParseMAC(targetMACStr) | |
if err != nil { | |
log.Printf("Invalid MAC address: %v", err) | |
return | |
} | |
} else { | |
targetMAC, err = net.ParseMAC(defaultTargetMAC) | |
if err != nil { | |
panic(err) | |
} | |
} | |
listenPortStr := os.Getenv("PORT") | |
listenPort, err := strconv.Atoi(listenPortStr) | |
if err != nil { | |
listenPort = defaultListenPort | |
} | |
log.Printf("TARGET_MAC: %s, LISTEN_PORT: %d", targetMAC, listenPort) | |
log.Println("Target and port can be set by environment variables TARGET_MAC and PORT") | |
cert, err := generateSelfSignedCert() | |
if err != nil { | |
log.Fatalf("Failed to generate certificate: %v", err) | |
} | |
tlsConfig := &tls.Config{ | |
Certificates: []tls.Certificate{cert}, | |
MinVersion: tls.VersionTLS12, | |
} | |
server := &http.Server{ | |
Addr: fmt.Sprintf(":%d", listenPort), | |
TLSConfig: tlsConfig, | |
Handler: http.HandlerFunc(handleWOL), | |
} | |
log.Printf("Starting server on port %d", listenPort) | |
log.Fatal(server.ListenAndServeTLS("", "")) | |
} | |
// GOARCH=arm go build -ldflags "-s -w" ./wol_go.go |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment