Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24d0900dab |
@@ -216,25 +216,27 @@ Each session has an IRC-style hostmask composed of three parts:
|
|||||||
- **nick** — the user's current nick (changes with `NICK` command)
|
- **nick** — the user's current nick (changes with `NICK` command)
|
||||||
- **username** — an ident-like identifier set at session creation (optional
|
- **username** — an ident-like identifier set at session creation (optional
|
||||||
`username` field in the session request; defaults to the nick)
|
`username` field in the session request; defaults to the nick)
|
||||||
- **hostname** — automatically resolved via reverse DNS of the connecting
|
- **hostname** — the reverse DNS name of the creating client's IP address,
|
||||||
client's IP address at session creation time
|
looked up at session creation time, or the IP address itself when the lookup
|
||||||
|
gives no name
|
||||||
- **ip** — the real IP address of the session creator, extracted from
|
- **ip** — the real IP address of the session creator, extracted from
|
||||||
`X-Forwarded-For`, `X-Real-IP`, or `RemoteAddr`
|
`X-Forwarded-For`, `X-Real-IP`, or `RemoteAddr`
|
||||||
|
|
||||||
Each **client connection** (created at session creation or login) also stores
|
Each **client connection** (created at session creation or login) also stores
|
||||||
its own **ip** and **hostname**, allowing the server to track the network origin
|
its own **ip** and **hostname**, found the same way. The session's hostname is
|
||||||
of each individual client independently from the session. Client-level IP and
|
the hostname of the client that created it, and every user can see it: in WHOIS
|
||||||
hostname are **not displayed to regular users**. They are only visible to
|
(311), WHO (352), USERHOST (302), NAMES (353) over the HTTP API, and
|
||||||
**server operators** (o-line) via `RPL_WHOISACTUALLY` (338) when the oper
|
`GET /api/v1/channels/{name}/members`. Only `RPL_WHOISACTUALLY` (338) is for
|
||||||
performs a WHOIS on a user.
|
**server operators** (o-line) alone: it gives the IP address and hostname of the
|
||||||
|
target's newest client.
|
||||||
|
|
||||||
The hostmask appears in:
|
The hostmask appears in:
|
||||||
|
|
||||||
- **WHOIS** (`311 RPL_WHOISUSER`) — `params` contains
|
- **WHOIS** (`311 RPL_WHOISUSER`) — `params` contains
|
||||||
`[nick, username, hostname, "*"]`
|
`[nick, username, hostname, "*"]`
|
||||||
- **WHOIS (oper-only)** (`338 RPL_WHOISACTUALLY`) — when the querier is a server
|
- **WHOIS (oper-only)** (`338 RPL_WHOISACTUALLY`) — when the querier is a server
|
||||||
operator, includes the target's current client IP and hostname (HTTP API only;
|
operator, includes the IP address and hostname of the target's newest client
|
||||||
the IRC listener's WHOIS does not send it)
|
(HTTP API only; the IRC listener's WHOIS does not send it)
|
||||||
- **WHO** (`352 RPL_WHOREPLY`) — `params` contains
|
- **WHO** (`352 RPL_WHOREPLY`) — `params` contains
|
||||||
`[channel, username, hostname, server, nick, flags]`
|
`[channel, username, hostname, server, nick, flags]`
|
||||||
|
|
||||||
@@ -438,7 +440,8 @@ The entire read/write loop for a client is two endpoints. Everything else
|
|||||||
```
|
```
|
||||||
┌─ Client ──────────────────────────────────────────────────┐
|
┌─ Client ──────────────────────────────────────────────────┐
|
||||||
│ │
|
│ │
|
||||||
│ 1. POST /api/v1/session {"nick":"alice"} │
|
│ 1. POST /api/v1/session │
|
||||||
|
│ {"nick":"alice","pow_token":"<hashcash stamp>"} │
|
||||||
│ → Set-Cookie: neoirc_auth=<random_hex>; HttpOnly; ... │
|
│ → Set-Cookie: neoirc_auth=<random_hex>; HttpOnly; ... │
|
||||||
│ → {"id":1, "nick":"alice"} │
|
│ → {"id":1, "nick":"alice"} │
|
||||||
│ │
|
│ │
|
||||||
@@ -471,7 +474,8 @@ The entire read/write loop for a client is two endpoints. Everything else
|
|||||||
```
|
```
|
||||||
┌─ Client A ────────────────────────────────────────────────┐
|
┌─ Client A ────────────────────────────────────────────────┐
|
||||||
│ │
|
│ │
|
||||||
│ 1. POST /api/v1/session {"nick":"alice"} │
|
│ 1. POST /api/v1/session │
|
||||||
|
│ {"nick":"alice","pow_token":"<hashcash stamp>"} │
|
||||||
│ → Set-Cookie: neoirc_auth=<cookie_a>; HttpOnly; ... │
|
│ → Set-Cookie: neoirc_auth=<cookie_a>; HttpOnly; ... │
|
||||||
│ → {"id":1, "nick":"alice"} │
|
│ → {"id":1, "nick":"alice"} │
|
||||||
│ │
|
│ │
|
||||||
@@ -1079,8 +1083,8 @@ RPL_WHOISCHANNELS (319), and RPL_ENDOFWHOIS (318).
|
|||||||
|
|
||||||
If the querying user is a **server operator** (authenticated via `OPER`), the
|
If the querying user is a **server operator** (authenticated via `OPER`), the
|
||||||
response over the HTTP API additionally includes RPL_WHOISACTUALLY (338) with
|
response over the HTTP API additionally includes RPL_WHOISACTUALLY (338) with
|
||||||
the target's current client IP address and hostname. The IRC listener's WHOIS
|
the IP address and hostname of the target's newest client. The IRC listener's
|
||||||
does not send it.
|
WHOIS does not send it.
|
||||||
|
|
||||||
**C2S:**
|
**C2S:**
|
||||||
|
|
||||||
@@ -1122,7 +1126,8 @@ LUSERS replies are also sent automatically during connection registration.
|
|||||||
|
|
||||||
Authenticate as a server operator (o-line). On success, the session gains oper
|
Authenticate as a server operator (o-line). On success, the session gains oper
|
||||||
privileges: it can use `KILL` and `WALLOPS`, and over the HTTP API its WHOIS
|
privileges: it can use `KILL` and `WALLOPS`, and over the HTTP API its WHOIS
|
||||||
responses include more (the target user's current client IP and hostname).
|
responses include more (the IP address and hostname of the target user's newest
|
||||||
|
client).
|
||||||
|
|
||||||
**C2S:**
|
**C2S:**
|
||||||
|
|
||||||
@@ -1346,10 +1351,10 @@ key ERR_BADCHANNELKEY (475), and one joining a full channel ERR_CHANNELISFULL
|
|||||||
`KICK #channel nick [:reason]`. The kicked user and all channel members receive
|
`KICK #channel nick [:reason]`. The kicked user and all channel members receive
|
||||||
the KICK message.
|
the KICK message.
|
||||||
|
|
||||||
**NOTICE:** Follows RFC 2812 over the HTTP API — NOTICE never triggers
|
**NOTICE:** Over the HTTP API, a NOTICE gets no RPL_AWAY and no hashcash check
|
||||||
auto-replies (including RPL_AWAY), and skips hashcash validation on +H channels
|
on `+H` channels, but it gets the same error numerics as PRIVMSG (411, 412, 401,
|
||||||
(servers and services use NOTICE). On the IRC listener, a NOTICE to a user who
|
403, 404). The IRC listener handles NOTICE exactly as PRIVMSG, so a NOTICE to a
|
||||||
is away does get RPL_AWAY.
|
user who is away gets RPL_AWAY there.
|
||||||
|
|
||||||
**ISUPPORT:** The server advertises `PREFIX=(ov)@+` in RPL_ISUPPORT (005), with
|
**ISUPPORT:** The server advertises `PREFIX=(ov)@+` in RPL_ISUPPORT (005), with
|
||||||
`CHANMODES=b,k,Hl,imnst` over the HTTP API and `CHANMODES=,,H,imnst` on the IRC
|
`CHANMODES=b,k,Hl,imnst` over the HTTP API and `CHANMODES=,,H,imnst` on the IRC
|
||||||
@@ -1448,9 +1453,11 @@ difficulty is advertised via `GET /api/v1/server` in the `hashcash_bits` field.
|
|||||||
| `pow_token` | string | Conditional | Hashcash stamp (required when server has `hashcash_bits` > 0) |
|
| `pow_token` | string | Conditional | Hashcash stamp (required when server has `hashcash_bits` > 0) |
|
||||||
|
|
||||||
The `username` field sets the user portion of the IRC hostmask
|
The `username` field sets the user portion of the IRC hostmask
|
||||||
(`nick!user@host`). The hostname is automatically resolved via reverse DNS of
|
(`nick!user@host`). The hostname is the reverse DNS name of the connecting
|
||||||
the connecting client's IP address at session creation time. Together these form
|
client's IP address, looked up at session creation time, or the IP address
|
||||||
the hostmask used in WHOIS, WHO, and ban matching (`+b`).
|
itself when the lookup gives no name; every user can see it (see
|
||||||
|
[Hostmask](#hostmask-nickuserhost)). Together these form the hostmask used in
|
||||||
|
WHOIS, WHO, NAMES, and ban matching (`+b`).
|
||||||
|
|
||||||
**Response:** `201 Created`
|
**Response:** `201 Created`
|
||||||
|
|
||||||
@@ -1729,12 +1736,12 @@ reference with all required and optional fields.
|
|||||||
All IRC commands return HTTP 200 OK, usually with `{"status": "error"}` when the
|
All IRC commands return HTTP 200 OK, usually with `{"status": "error"}` when the
|
||||||
reply is an error numeric (a WHOIS for an unknown nick still gets
|
reply is an error numeric (a WHOIS for an unknown nick still gets
|
||||||
`{"status": "ok"}`), and otherwise a status of the command's own (see each
|
`{"status": "ok"}`), and otherwise a status of the command's own (see each
|
||||||
command). IRC-level success and error responses are delivered as **numeric
|
command). **Numeric replies**, for success and for errors, are delivered through
|
||||||
replies** through the message queue (see
|
the message queue (see [Numeric Reply Codes](#numeric-reply-codes-s2c-only)); a
|
||||||
[Numeric Reply Codes](#numeric-reply-codes-s2c-only)); `PING` is the exception,
|
command that has none, such as a successful `PRIVMSG`, is answered by the HTTP
|
||||||
its `PONG` is the HTTP response body. HTTP error codes (4xx/5xx) are reserved
|
response alone, and `PING`'s `PONG` is the HTTP response body. HTTP error codes
|
||||||
for transport-level problems: malformed JSON (400), missing/invalid auth cookies
|
(4xx/5xx) are reserved for transport-level problems: malformed JSON (400),
|
||||||
(401), and server errors (500).
|
missing/invalid auth cookies (401), and server errors (500).
|
||||||
|
|
||||||
**HTTP errors (transport-level only):**
|
**HTTP errors (transport-level only):**
|
||||||
|
|
||||||
@@ -2402,12 +2409,12 @@ applied; `001_initial.sql` creates the tables below.
|
|||||||
#### `sessions`
|
#### `sessions`
|
||||||
|
|
||||||
| Column | Type | Description |
|
| Column | Type | Description |
|
||||||
| --------------- | -------- | ------------------------------------------------------------- |
|
| --------------- | -------- | ------------------------------------------------------------------------------- |
|
||||||
| `id` | INTEGER | Primary key (auto-increment) |
|
| `id` | INTEGER | Primary key (auto-increment) |
|
||||||
| `uuid` | TEXT | Unique session UUID |
|
| `uuid` | TEXT | Unique session UUID |
|
||||||
| `nick` | TEXT | Unique nick |
|
| `nick` | TEXT | Unique nick |
|
||||||
| `username` | TEXT | IRC ident/username portion of the hostmask (defaults to nick) |
|
| `username` | TEXT | IRC ident/username portion of the hostmask (defaults to nick) |
|
||||||
| `hostname` | TEXT | Reverse DNS hostname of the connecting client IP |
|
| `hostname` | TEXT | Reverse DNS name of the creating client's IP, or the IP itself when it has none |
|
||||||
| `ip` | TEXT | Real IP address of the session creator |
|
| `ip` | TEXT | Real IP address of the session creator |
|
||||||
| `is_oper` | INTEGER | Server operator, user mode `+o` (0 = no, 1 = yes) |
|
| `is_oper` | INTEGER | Server operator, user mode `+o` (0 = no, 1 = yes) |
|
||||||
| `is_wallops` | INTEGER | User mode `+w`, receives `WALLOPS` (0 = no, 1 = yes) |
|
| `is_wallops` | INTEGER | User mode `+w`, receives `WALLOPS` (0 = no, 1 = yes) |
|
||||||
@@ -2422,13 +2429,13 @@ Index on `(uuid)`.
|
|||||||
#### `clients`
|
#### `clients`
|
||||||
|
|
||||||
| Column | Type | Description |
|
| Column | Type | Description |
|
||||||
| ------------ | -------- | ---------------------------------------------------------- |
|
| ------------ | -------- | ----------------------------------------------------------------------- |
|
||||||
| `id` | INTEGER | Primary key (auto-increment) |
|
| `id` | INTEGER | Primary key (auto-increment) |
|
||||||
| `uuid` | TEXT | Unique client UUID |
|
| `uuid` | TEXT | Unique client UUID |
|
||||||
| `session_id` | INTEGER | FK → sessions.id (cascade delete) |
|
| `session_id` | INTEGER | FK → sessions.id (cascade delete) |
|
||||||
| `token` | TEXT | Auth cookie value (SHA-256 hash of the 64-hex-char cookie) |
|
| `token` | TEXT | Auth cookie value (SHA-256 hash of the 64-hex-char cookie) |
|
||||||
| `ip` | TEXT | Real IP address of this client connection |
|
| `ip` | TEXT | Real IP address of this client connection |
|
||||||
| `hostname` | TEXT | Reverse DNS hostname of this client connection |
|
| `hostname` | TEXT | Reverse DNS name of this client's IP, or the IP itself when it has none |
|
||||||
| `created_at` | DATETIME | Client creation time |
|
| `created_at` | DATETIME | Client creation time |
|
||||||
| `last_seen` | DATETIME | Last authenticated HTTP API request (or creation) |
|
| `last_seen` | DATETIME | Last authenticated HTTP API request (or creation) |
|
||||||
|
|
||||||
@@ -2671,8 +2678,22 @@ IRC_LISTEN_ADDR: ""
|
|||||||
|
|
||||||
Messages sent by IRC clients appear in channels visible to HTTP/JSON API clients
|
Messages sent by IRC clients appear in channels visible to HTTP/JSON API clients
|
||||||
and vice versa. The IRC listener and HTTP API share the same database, broker,
|
and vice versa. The IRC listener and HTTP API share the same database, broker,
|
||||||
and session infrastructure. A user connected via IRC and a user connected via
|
and session infrastructure, so a user connected via IRC and a user connected via
|
||||||
the HTTP API can communicate in the same channels seamlessly.
|
the HTTP API can talk in the same channels, with these gaps today:
|
||||||
|
|
||||||
|
- An IRC listener user receives only the first line of a multi-line `body`.
|
||||||
|
- A `+k`, `+l` or `+b` change made over the HTTP API reaches IRC listener
|
||||||
|
members without its key, limit or mask.
|
||||||
|
- The IRC listener's `JOIN` accepts any channel name, while over the HTTP API a
|
||||||
|
name that is not `#` followed by 1–63 letters, digits, `_` or `-` gets
|
||||||
|
ERR_NOSUCHCHANNEL (403), so HTTP API users cannot join such a channel.
|
||||||
|
- The IRC listener does not pass on a `PRIVMSG`, `NOTICE`, `JOIN`, `PART`,
|
||||||
|
`NICK` or `QUIT` whose sender's nick matches the user's own nick ignoring
|
||||||
|
case, so an IRC listener user `alice` never sees these from `Alice`, although
|
||||||
|
nicks are case-sensitive.
|
||||||
|
|
||||||
|
https://git.eeqj.de/sneak/neoirc/issues/127 tracks the first three and
|
||||||
|
https://git.eeqj.de/sneak/neoirc/issues/128 the last.
|
||||||
|
|
||||||
### Docker Usage
|
### Docker Usage
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user