small fix
This commit is contained in:
parent
b8f8e5607c
commit
d76e8245e0
16
admin.log
16
admin.log
@ -20,3 +20,19 @@
|
|||||||
2025/12/22 20:35:10 ADMIN ADD domain=photo.phone.local ip=192.168.31.108:57431
|
2025/12/22 20:35:10 ADMIN ADD domain=photo.phone.local ip=192.168.31.108:57431
|
||||||
2025/12/23 13:11:21 ADMIN ADD domain=api.phone.local ip=192.168.31.108:51617
|
2025/12/23 13:11:21 ADMIN ADD domain=api.phone.local ip=192.168.31.108:51617
|
||||||
2025/12/23 13:16:27 ADMIN ADD domain=api.phone.key ip=192.168.31.108:51942
|
2025/12/23 13:16:27 ADMIN ADD domain=api.phone.key ip=192.168.31.108:51942
|
||||||
|
2025/12/23 13:59:39 ADMIN ADD domain=api.phone.local ip=192.168.31.108:54219
|
||||||
|
2025/12/24 11:09:00 ADMIN AUTH_MISSING ip=127.0.0.1:62049
|
||||||
|
2025/12/24 11:09:18 ADMIN ADD domain=api.phone.local ip=127.0.0.1:62049
|
||||||
|
2025/12/24 11:46:22 ADMIN ADD domain=photo.phone.local ip=192.168.188.24:49477
|
||||||
|
2025/12/24 12:04:15 ADMIN AUTH_MISSING ip=192.168.188.24:54980
|
||||||
|
2025/12/24 16:27:27 ADMIN ADD domain=api.phone.local ip=192.168.31.108:54824
|
||||||
|
2025/12/24 16:35:37 ADMIN ADD domain=photo.phone.local ip=192.168.31.108:54824
|
||||||
|
2025/12/26 08:07:58 ADMIN DELETE domain=photo.phone.local ip=192.168.31.108:50958
|
||||||
|
2025/12/26 08:08:55 ADMIN ADD domain=photo.phone.local ip=192.168.31.108:50958
|
||||||
|
2025/12/26 08:22:28 ADMIN ADD domain=api.phone.local ip=192.168.31.108:51483
|
||||||
|
2025/12/26 08:22:40 ADMIN ADD domain=photo.phone.local ip=192.168.31.108:51483
|
||||||
|
2025/12/26 08:25:35 ADMIN ADD domain=photo.phone.local ip=192.168.31.108:51483
|
||||||
|
2025/12/26 16:44:18 ADMIN ADD domain=api.phone.local ip=192.168.31.108:49806
|
||||||
|
2025/12/26 16:44:27 ADMIN ADD domain=photo.phone.local ip=192.168.31.108:49806
|
||||||
|
2025/12/26 16:46:39 ADMIN ADD domain=api.phone.local ip=192.168.31.108:49877
|
||||||
|
2025/12/26 16:46:49 ADMIN ADD domain=photo.phone.local ip=192.168.31.108:49877
|
||||||
|
|||||||
127
admin/admin.html
127
admin/admin.html
@ -1,127 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Relay Admin Panel</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-family: sans-serif;
|
|
||||||
max-width: 600px;
|
|
||||||
margin: 40px auto;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
input, button {
|
|
||||||
padding: 6px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
ul {
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
|
||||||
li {
|
|
||||||
margin: 6px 0;
|
|
||||||
}
|
|
||||||
.error {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<h1>Relay Admin Panel</h1>
|
|
||||||
|
|
||||||
<label>
|
|
||||||
API Key:
|
|
||||||
<input id="apiKey" type="password" style="width: 100%" />
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h3>Registered domains</h3>
|
|
||||||
<button onclick="loadDomains()">Refresh</button>
|
|
||||||
<ul id="domains"></ul>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<h3>Add domain</h3>
|
|
||||||
<input id="newDomain" placeholder="example.phone.local" />
|
|
||||||
<button onclick="addDomain()">Add</button>
|
|
||||||
|
|
||||||
<p id="status" class="error"></p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const apiBase = "/domains";
|
|
||||||
|
|
||||||
function headers() {
|
|
||||||
return {
|
|
||||||
"apikey": document.getElementById("apiKey").value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadDomains() {
|
|
||||||
const res = await fetch(apiBase, { headers: headers() });
|
|
||||||
if (!res.ok) {
|
|
||||||
showError(res);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const text = await res.text();
|
|
||||||
const list = document.getElementById("domains");
|
|
||||||
list.innerHTML = "";
|
|
||||||
|
|
||||||
text.trim().split("\n").forEach(domain => {
|
|
||||||
if (!domain) return;
|
|
||||||
|
|
||||||
const li = document.createElement("li");
|
|
||||||
li.textContent = domain + " ";
|
|
||||||
|
|
||||||
const btn = document.createElement("button");
|
|
||||||
btn.textContent = "Delete";
|
|
||||||
btn.onclick = () => deleteDomain(domain);
|
|
||||||
|
|
||||||
li.appendChild(btn);
|
|
||||||
list.appendChild(li);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function addDomain() {
|
|
||||||
const domain = document.getElementById("newDomain").value;
|
|
||||||
if (!domain) return;
|
|
||||||
|
|
||||||
const res = await fetch(`${apiBase}?domain=${encodeURIComponent(domain)}`, {
|
|
||||||
method: "POST",
|
|
||||||
headers: headers()
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!res.ok) {
|
|
||||||
showError(res);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById("newDomain").value = "";
|
|
||||||
loadDomains();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function deleteDomain(domain) {
|
|
||||||
const res = await fetch(`${apiBase}?domain=${encodeURIComponent(domain)}`, {
|
|
||||||
method: "DELETE",
|
|
||||||
headers: headers()
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!res.ok) {
|
|
||||||
showError(res);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadDomains();
|
|
||||||
}
|
|
||||||
|
|
||||||
function showError(res) {
|
|
||||||
document.getElementById("status").textContent =
|
|
||||||
`Error: ${res.status} ${res.statusText}`;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -4,6 +4,8 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"relay/device"
|
||||||
|
tunnelpb "relay/proto/tunnel"
|
||||||
"relay/registry"
|
"relay/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -40,19 +42,25 @@ func domainsHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
case "DELETE":
|
case "DELETE":
|
||||||
domain := strings.ToLower(r.URL.Query().Get("domain"))
|
domain := strings.ToLower(r.URL.Query().Get("domain"))
|
||||||
|
|
||||||
|
var dev *device.Device
|
||||||
|
var existed bool
|
||||||
|
|
||||||
registry.Global.Mu.Lock()
|
registry.Global.Mu.Lock()
|
||||||
if _, exists := registry.Global.Domains[domain]; exists {
|
if d, ok := registry.Global.Domains[domain]; ok {
|
||||||
|
existed = true
|
||||||
|
dev = d
|
||||||
delete(registry.Global.Domains, domain)
|
delete(registry.Global.Domains, domain)
|
||||||
adminLogger.Printf(
|
|
||||||
"ADMIN DELETE domain=%s ip=%s",
|
|
||||||
domain, r.RemoteAddr,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
registry.Global.Mu.Unlock()
|
registry.Global.Mu.Unlock()
|
||||||
|
|
||||||
w.Write([]byte("deleted\n"))
|
if existed && dev != nil {
|
||||||
|
dev.SendFrame(&tunnelpb.Frame{
|
||||||
|
Type: tunnelpb.FrameType_FRAME_BIND_REJECTED,
|
||||||
|
Payload: []byte(domain),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
http.Error(w, "method not allowed", 405)
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ type Device struct {
|
|||||||
func NewDevice(stream tunnelpb.TunnelService_TunnelServer) *Device {
|
func NewDevice(stream tunnelpb.TunnelService_TunnelServer) *Device {
|
||||||
d := &Device{
|
d := &Device{
|
||||||
stream: stream,
|
stream: stream,
|
||||||
sendCh: make(chan *tunnelpb.Frame, 128), // backpressure here
|
sendCh: make(chan *tunnelpb.Frame, 128),
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
streams: make(map[uint32]net.Conn),
|
streams: make(map[uint32]net.Conn),
|
||||||
streamDone: make(map[uint32]chan struct{}),
|
streamDone: make(map[uint32]chan struct{}),
|
||||||
|
|||||||
@ -35,7 +35,7 @@ func handleClientTCP(conn net.Conn) {
|
|||||||
streamID := dev.AllocateStreamID()
|
streamID := dev.AllocateStreamID()
|
||||||
done := dev.AddStream(streamID, conn)
|
done := dev.AddStream(streamID, conn)
|
||||||
|
|
||||||
log.Printf("Client [%s] → device (stream %d)\n", sni, streamID)
|
log.Printf("Client [%s] -> device (stream %d)\n", sni, streamID)
|
||||||
|
|
||||||
dev.SendFrame(&tunnelpb.Frame{
|
dev.SendFrame(&tunnelpb.Frame{
|
||||||
Type: tunnelpb.FrameType_FRAME_OPEN,
|
Type: tunnelpb.FrameType_FRAME_OPEN,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user