forked from yene/nupnp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
689 additions
and
122 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Use the official Go image to build the application | ||
FROM golang:1.22 AS builder | ||
|
||
# Set the Current Working Directory inside the container | ||
WORKDIR /app | ||
|
||
# Copy go.mod and go.sum to install dependencies | ||
COPY go.mod go.sum ./ | ||
|
||
# Download all dependencies. They will be cached if the go.mod and go.sum files are not changed. | ||
RUN go mod download | ||
|
||
# Copy the source code into the container | ||
COPY . . | ||
|
||
# Build the Go application | ||
RUN go build -o whereisit . | ||
|
||
# Use a smaller image for deployment | ||
FROM alpine:3.18 | ||
|
||
# Install certificates for HTTPS | ||
RUN apk --no-cache add ca-certificates | ||
|
||
# Create a folder for certificates (assuming you have your own SSL cert and key) | ||
RUN mkdir -p /etc/ssl/certs && mkdir -p /etc/ssl/private | ||
|
||
# Copy the SSL certificates (adjust paths as necessary) | ||
COPY ./certs/server.crt /etc/ssl/certs/ | ||
COPY ./certs/server.key /etc/ssl/private/ | ||
|
||
# Copy the built Go binary from the builder | ||
COPY --from=builder /app/main /app/main | ||
|
||
# Expose HTTP on port 80 and HTTPS on port 443 | ||
EXPOSE 80 443 | ||
|
||
# Command to run the executable | ||
CMD ["/app/whereisit"] |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import argparse | ||
import requests | ||
import json | ||
import time | ||
import socket | ||
import os | ||
|
||
STATE_FILE = "/tmp/ip_state.json" # Store the last IP and timestamp | ||
|
||
def get_local_ip(): | ||
""" | ||
Retrieve the current local IP address. | ||
""" | ||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | ||
try: | ||
# This doesn't actually send data; it's just to get the IP | ||
s.connect(('8.8.8.8', 80)) | ||
return s.getsockname()[0] | ||
except Exception as e: | ||
print(f"Error retrieving local IP: {e}") | ||
return None | ||
finally: | ||
s.close() | ||
|
||
def get_hostname(): | ||
""" | ||
Retrieve the local machine's hostname. | ||
""" | ||
return socket.gethostname() | ||
|
||
def get_serial_number(): | ||
""" | ||
Retrieve the device's serial number. | ||
This is an example command that works on many Linux systems. | ||
Adjust as needed based on your hardware. | ||
""" | ||
try: | ||
# This command works on many Linux systems | ||
serial = os.popen("cat /etc/machine-id").read().strip() | ||
if not serial: | ||
serial = "UNKNOWN_SERIAL" | ||
return serial | ||
except Exception as e: | ||
print(f"Error retrieving serial number: {e}") | ||
return "UNKNOWN_SERIAL" | ||
|
||
def load_state(): | ||
""" | ||
Load the last known state (IP and timestamp) from file. | ||
""" | ||
if os.path.exists(STATE_FILE): | ||
with open(STATE_FILE, 'r') as f: | ||
return json.load(f) | ||
return None | ||
|
||
def save_state(ip, timestamp): | ||
""" | ||
Save the current IP and timestamp to file. | ||
""" | ||
with open(STATE_FILE, 'w') as f: | ||
json.dump({"ip": ip, "timestamp": timestamp}, f) | ||
|
||
|
||
def send_ip_update(ip, name, id, server_ip, server_port): | ||
""" | ||
Send the local IP to the REST server as a JSON payload. | ||
""" | ||
url = f"http://{server_ip}:{server_port}/api/register" | ||
payload = { | ||
"name": name, | ||
"address": ip, | ||
"id": id | ||
} | ||
try: | ||
response = requests.post(url, json=payload) | ||
if response.status_code == 200: | ||
print(f"Successfully sent IP update to {server_ip}:{server_port}: {ip}") | ||
else: | ||
print(f"Failed to send IP update. Status code: {response.status_code}") | ||
except Exception as e: | ||
print(f"Error sending IP update: {e}") | ||
|
||
def main(): | ||
# Parse command line arguments | ||
parser = argparse.ArgumentParser(description="Send local IP to a \"whereisit\" server when it changes, or every 24 hours.") | ||
parser.add_argument("--server-ip", required=True, help="The IP address of the REST server.") | ||
parser.add_argument("--server-port", required=True, help="The port number of the REST server.") | ||
args = parser.parse_args() | ||
server_ip = args.server_ip | ||
server_port = args.server_port | ||
|
||
while True: | ||
current_ip = get_local_ip() | ||
|
||
if not current_ip: | ||
print("Could not determine local IP. Retrying in 10 minutes.") | ||
time.sleep(600) # Retry in 10 minutes | ||
continue | ||
|
||
hostname = get_hostname() | ||
identifier = get_serial_number() | ||
|
||
state = load_state() | ||
current_time = time.time() | ||
|
||
# Check if state exists and if 24 hours have passed or IP has changed | ||
if not state or state['ip'] != current_ip or (current_time - state['timestamp'] > 86400): | ||
send_ip_update(current_ip, hostname, identifier, server_ip, server_port) | ||
save_state(current_ip, current_time) | ||
else: | ||
print(f"No changes in IP. Last sent IP: {state['ip']}. Will check again in 10 minutes.") | ||
|
||
# Wait 10 minutes before checking again | ||
time.sleep(600) | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import argparse | ||
import requests | ||
|
||
from typing import List | ||
|
||
def get_devices(server_ip, server_port) -> List[str]: | ||
""" | ||
Send the local IP to the REST server as a JSON payload. | ||
""" | ||
url = f"http://{server_ip}:{server_port}/api/devices" | ||
try: | ||
response = requests.get(url) | ||
if response.status_code == 200: | ||
print(f"Successfully sent IP update to {server_ip}:{server_port}: {ip}") | ||
print(response.content) | ||
else: | ||
print(f"Failed to send IP update. Status code: {response.status_code}") | ||
except Exception as e: | ||
print(f"Error sending IP update: {e}") | ||
|
||
def main(): | ||
# Parse command line arguments | ||
parser = argparse.ArgumentParser(description="Get devices inside the network from a \"whereisit\" server.") | ||
parser.add_argument("--server-ip", required=True, help="The IP address of the REST server.") | ||
parser.add_argument("--server-port", required=True, help="The port number of the REST server.") | ||
parser.add_argument("--identifier", required=False, help="The identifier of the device searched for.") | ||
args = parser.parse_args() | ||
server_ip = args.server_ip | ||
server_port = args.server_port | ||
|
||
deviceList = get_devices(server_ip, server_port) | ||
|
||
if deviceList.count > 0: | ||
for device in deviceList: | ||
print("Device:", device) | ||
else: | ||
print("No device found") | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
#!/usr/bin/env sh | ||
|
||
DEVICE_NAME=$(hostname) | ||
|
||
get_serial_number() { | ||
local serial_number="" | ||
|
||
# Detect operating system | ||
os_name=$(uname) | ||
if [[ "$os_name" == "Darwin" ]]; then | ||
serial_number=$(system_profiler SPHardwareDataType | grep "Serial Number (system)" | awk '{print $NF}') | ||
elif [[ "$os_name" == "Linux" ]]; then | ||
serial_number=$(cat /etc/machine-id) | ||
else | ||
echo "Unsupported operating system: $os_name" | ||
return 1 | ||
fi | ||
echo "$serial_number" | ||
} | ||
|
||
get_lan_ip() { | ||
local ip_address="" | ||
|
||
# Detect operating system | ||
os_name=$(uname) | ||
|
||
if [[ "$os_name" == "Darwin" ]]; then | ||
# macOS - Get LAN IP using ifconfig | ||
ip_address=$(ifconfig en0 | grep "inet " | awk '{print $2}') | ||
elif [[ "$os_name" == "Linux" ]]; then | ||
# Linux - Get LAN IP using hostname or ip command | ||
if command -v ip &> /dev/null; then | ||
ip_address=$(ip addr show $(ip route show default | awk '/default/ {print $5}') | grep 'inet ' | awk '{print $2}' | cut -d/ -f1) | ||
else | ||
ip_address=$(hostname -I | awk '{print $1}') | ||
fi | ||
else | ||
echo "Unsupported operating system: $os_name" | ||
return 1 | ||
fi | ||
|
||
echo "$ip_address" | ||
} | ||
|
||
get_os_version() { | ||
OS_TYPE=$(uname) | ||
|
||
if [[ "$OS_TYPE" == "Darwin" ]]; then | ||
# macOS (Darwin) version | ||
OS_VERSION=$(sw_vers -productVersion) | ||
echo "Operating System: macOS" | ||
echo "Version: $OS_VERSION" | ||
elif [[ "$OS_TYPE" == "Linux" ]]; then | ||
# Linux version | ||
if [ -f /etc/os-release ]; then | ||
. /etc/os-release | ||
echo "Operating System: $NAME" | ||
echo "Version: $VERSION" | ||
else | ||
echo "Operating System: Linux" | ||
echo "Version information not found." | ||
fi | ||
else | ||
echo "Unsupported operating system: $OS_TYPE" | ||
return 1 | ||
fi | ||
} | ||
|
||
DEVICE_ID=$(get_serial_number) | ||
DEVICE_IP=$(get_lan_ip) | ||
|
||
if [ "$#" -ne 2 ]; then | ||
echo "Usage: $0 <server_ip> <server_port>" | ||
exit 1 | ||
fi | ||
|
||
SERVER_IP=$1 | ||
SERVER_PORT=$2 | ||
|
||
PAYLOAD=$(cat <<EOF | ||
{ | ||
"name": "${DEVICE_NAME}", | ||
"id": "${DEVICE_ID}", | ||
"address": "${DEVICE_IP}" | ||
} | ||
EOF | ||
) | ||
HEADERS="-H 'Content-Type: application/json'" | ||
|
||
if [[ "$server_ip" == "localhost" || "$server_ip" == "127.0.0.1" ]]; then | ||
headers+=" -H 'x-real-ip: ${DEVICE_IP}'" | ||
fi | ||
|
||
WHEREISIT_URL="http://${SERVER_IP}:${SERVER_PORT}/api/register" | ||
|
||
eval "curl -X POST $WHEREISIT_URL $HEADERS -d '$PAYLOAD'" | ||
|
||
echo "Payload sent: ${PAYLOAD}" | ||
echo "----- DONE -----" |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#!/usr/bin/env sh | ||
|
||
if [ "$#" -ne 2 ]; then | ||
echo "Usage: $0 <server_ip> <server_port>" | ||
exit 1 | ||
fi | ||
|
||
SERVER_IP=$1 | ||
SERVER_PORT=$2 | ||
|
||
curl -X GET "${SERVER_IP}:${SERVER_PORT}/api/devices" | ||
|
||
echo "----- DONE -----" |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[Unit] | ||
Description=whereistit client run every 2 hours | ||
|
||
[Service] | ||
ExecStart=/usr/local/bin/whereistit_client.sh | ||
|
||
[Timer] | ||
OnBootSec=3min | ||
OnUnitActiveSec=2h | ||
Persistent=true | ||
|
||
[Install] | ||
WantedBy=multi-user.target |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,10 @@ | ||
module whereisit | ||
|
||
go 1.22.4 | ||
|
||
require github.com/gorilla/mux v1.8.1 | ||
|
||
require ( | ||
github.com/stretchr/testify v1.9.0 // indirect | ||
gopkg.in/ini.v1 v1.67.0 | ||
) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= | ||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= | ||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= | ||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains 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
Oops, something went wrong.