Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe7304ac7f | ||
|
|
e5d39c984b | ||
|
|
5e45f21e35 | ||
|
|
5321a238b8 | ||
|
|
083bc14972 | ||
|
|
11aaccba9b |
+31
-2
@@ -1338,6 +1338,23 @@ async function subscribeToConfiguration() {
|
||||
console.log('No configuration events were received');
|
||||
}
|
||||
},
|
||||
async onauth(challenge) {
|
||||
// NIP-42 authentication: relay sent AUTH challenge, sign and respond
|
||||
console.log('🔐 NIP-42 AUTH challenge received:', challenge);
|
||||
try {
|
||||
if (!window.nostr) {
|
||||
console.error('NIP-42 auth required but no nostr extension available');
|
||||
return;
|
||||
}
|
||||
const url = relayConnectionUrl.value.trim();
|
||||
const authEvent = window.NostrTools.nip42.makeAuthEvent(url, challenge);
|
||||
const signedAuthEvent = await window.nostr.signEvent(authEvent);
|
||||
console.log('✅ NIP-42 AUTH event signed, responding to challenge');
|
||||
return signedAuthEvent;
|
||||
} catch (authError) {
|
||||
console.error('NIP-42 AUTH failed:', authError.message);
|
||||
}
|
||||
},
|
||||
onclose(reason) {
|
||||
console.log('Subscription closed:', reason);
|
||||
// Reset subscription state to allow re-subscription
|
||||
@@ -5467,9 +5484,21 @@ async function sendAdminCommand(commandArray) {
|
||||
throw new Error('Event signing failed');
|
||||
}
|
||||
|
||||
// Publish via SimplePool with detailed error diagnostics
|
||||
// Publish via SimplePool with NIP-42 auth support
|
||||
const url = relayConnectionUrl.value.trim();
|
||||
const publishPromises = relayPool.publish([url], signedEvent);
|
||||
const publishPromises = relayPool.publish([url], signedEvent, {
|
||||
async onauth(challenge) {
|
||||
console.log('🔐 NIP-42 AUTH challenge during publish:', challenge);
|
||||
try {
|
||||
const authEvent = window.NostrTools.nip42.makeAuthEvent(url, challenge);
|
||||
const signedAuthEvent = await window.nostr.signEvent(authEvent);
|
||||
console.log('✅ NIP-42 AUTH signed for publish');
|
||||
return signedAuthEvent;
|
||||
} catch (authError) {
|
||||
console.error('NIP-42 AUTH failed during publish:', authError.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Use Promise.allSettled to capture per-relay outcomes
|
||||
const results = await Promise.allSettled(publishPromises);
|
||||
|
||||
File diff suppressed because one or more lines are too long
+17
-2
@@ -196,8 +196,23 @@ void ip_ban_cleanup(void) {
|
||||
int window_expired = (entry->first_failure == 0 || (now - entry->first_failure) > window_sec * 10);
|
||||
|
||||
if (ban_expired && window_expired && entry->failure_count == 0) {
|
||||
memset(entry, 0, sizeof(ip_ban_entry_t));
|
||||
cleaned++;
|
||||
// Retain ban_count for 24 hours after the last ban expired.
|
||||
// This ensures exponential backoff persists if the IP returns within 24 hours.
|
||||
// After 24 hours of inactivity, fully clean the entry.
|
||||
int retain_sec = 86400; // 24 hours
|
||||
int last_ban_expired_long_ago = (entry->banned_until == 0 ||
|
||||
(now - entry->banned_until) > retain_sec);
|
||||
|
||||
if (last_ban_expired_long_ago) {
|
||||
// Fully clean — IP has been gone for 24+ hours, start fresh if it returns
|
||||
memset(entry, 0, sizeof(ip_ban_entry_t));
|
||||
cleaned++;
|
||||
} else {
|
||||
// Keep entry alive but reset transient fields — preserve ban_count
|
||||
entry->failure_count = 0;
|
||||
entry->first_failure = 0;
|
||||
// banned_until and ban_count preserved intentionally
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -13,8 +13,8 @@
|
||||
// Using CRELAY_ prefix to avoid conflicts with nostr_core_lib VERSION macros
|
||||
#define CRELAY_VERSION_MAJOR 1
|
||||
#define CRELAY_VERSION_MINOR 2
|
||||
#define CRELAY_VERSION_PATCH 19
|
||||
#define CRELAY_VERSION "v1.2.19"
|
||||
#define CRELAY_VERSION_PATCH 25
|
||||
#define CRELAY_VERSION "v1.2.25"
|
||||
|
||||
// Relay metadata (authoritative source for NIP-11 information)
|
||||
#define RELAY_NAME "C-Relay"
|
||||
|
||||
+17
-14
@@ -463,17 +463,6 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
|
||||
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
DEBUG_TRACE("WebSocket connection established");
|
||||
|
||||
// Check IP ban before doing any work — reject banned IPs immediately
|
||||
{
|
||||
char check_ip[CLIENT_IP_MAX_LENGTH] = {0};
|
||||
const char* fwd = lws_get_peer_simple(wsi, check_ip, sizeof(check_ip));
|
||||
(void)fwd;
|
||||
if (ip_ban_is_banned(check_ip)) {
|
||||
DEBUG_LOG("Rejecting banned IP %s at connection establishment", check_ip);
|
||||
return -1; // Close connection immediately
|
||||
}
|
||||
}
|
||||
memset(pss, 0, sizeof(*pss));
|
||||
pthread_mutex_init(&pss->session_lock, NULL);
|
||||
|
||||
@@ -558,6 +547,14 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
|
||||
pss->challenge_created = 0;
|
||||
pss->challenge_expires = 0;
|
||||
|
||||
// Check IP ban using the resolved client IP (which may be from X-Forwarded-For).
|
||||
// This must happen AFTER pss->client_ip is populated so the same IP string
|
||||
// is used for both ban recording (at CLOSED) and ban checking (here).
|
||||
if (ip_ban_is_banned(pss->client_ip)) {
|
||||
DEBUG_LOG("Rejecting banned IP %s at connection establishment", pss->client_ip);
|
||||
return -1; // Close connection immediately — no challenge, no processing
|
||||
}
|
||||
|
||||
// Set libwebsockets auth timeout: if NIP-42 auth is required and the client
|
||||
// doesn't authenticate within nip42_auth_timeout_sec seconds, lws will close
|
||||
// the connection automatically — even if the client never sends a message.
|
||||
@@ -2492,11 +2489,17 @@ int start_websocket_relay(int port_override, int strict_port) {
|
||||
}
|
||||
}
|
||||
|
||||
// Check connection age limits (every 60 seconds)
|
||||
// Check connection age limits and run IP ban maintenance (every 60 seconds)
|
||||
int max_connection_seconds = get_config_int("max_connection_seconds", 86400);
|
||||
if (max_connection_seconds > 0 && (current_time - last_connection_age_check >= 60)) {
|
||||
if (current_time - last_connection_age_check >= 60) {
|
||||
last_connection_age_check = current_time;
|
||||
check_connection_age(max_connection_seconds);
|
||||
if (max_connection_seconds > 0) {
|
||||
check_connection_age(max_connection_seconds);
|
||||
} else {
|
||||
// Even when connection age limit is disabled, run IP ban maintenance
|
||||
ip_ban_cleanup();
|
||||
ip_ban_log_stats();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user