1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
# N2Usenet HTTPS/Nym
N2Usenet HTTPS/Nym is the standalone clearnet-facing web gateway for posting to
Usenet through the existing TCPReset Mail2News and NNTP infrastructure.
It is intentionally separate from the onion `/compose/` deployment. M2Usenet
remains the onion-only compose UI integrated into Onion Newsreader; N2Usenet is
the standalone HTTPS/Nym service for `n2usenet.virebent.art`.
## Flow
```text
Browser
-> HTTPS n2usenet.virebent.art
-> N2Usenet Go backend
-> local nym-socks5-client
-> Nym network requester
-> SMTP submission 51.178.55.22:587 STARTTLS + AUTH
(TLS name mail.virebent.art)
-> Postfix with SPF/DKIM/DMARC
-> mail2news@mail2news.tcpreset.net
-> Mail2News gateway
-> Tor SOCKS
-> peannyjkqwqfynd24p6dszvtchkq7hfkwymi5by5y332wmosy5dwfaqd.onion:119
-> news.tcpreset.net INN
```
## Build
```bash
go test ./...
go build -o n2usenet ./cmd/n2usenet
go build -o n2u-check ./cmd/n2u-check
```
## Features
- **Proof-of-work anti-spam**: client computes a hashcash-style token before
submission; the server only verifies it (never computes it) and caches
spent tokens in memory with a TTL to reject replays.
- **Ed25519 signing**: the message is signed locally in the browser with the
self-hosted TweetNaCl (`nacl`) library. The secret key never leaves the
device; the server only verifies the signature against the submitted text.
- **VFACE identicon / `Face:` header**: the complete
`username|email|public-key` identity deterministically generates a visual
identicon (`identicons-cli` engine, same backend as
`identicons.virebent.art`), embedded as a folded `Face:` header alongside
`X-Ed25519-Pub`/`X-Ed25519-Sig` so any reader can re-verify authorship.
- **Optional persistent identity (save/load)**: after generating a keypair,
"Save Identity" downloads a JSON file with the public/secret key and
username/email. Loading that file later restores the complete identity, so
the same identicon keeps appearing across posts and lets readers associate
later signatures with the same public key. Username, email, and keypair are
locked together while that identity is active. This is entirely optional:
skip it for a fresh, unlinkable throwaway identity on every post. The file
contains the secret key in clear, so it must be kept private, anyone holding
it can sign as that identity.
- **Usenet-style line wrapping**: before signing, the message body is
automatically word-wrapped to 72 columns (RFC 1855 Netiquette
convention), for compatibility with classic terminal-based newsreaders.
Blank lines and quoted lines (`>`) are left untouched. The wrap happens
client-side, before the Ed25519 signature is computed, so the signature
always covers the exact bytes that end up posted.
- **CSRF protection and per-IP rate limiting**, both server-side.
- **No access logs, ephemeral state**: identity and form data are kept only
in browser tab memory and wiped after a successful send.
- **Nym followed by Tor for separate hops**: SOCKS5 through a local
`nym-socks5-client`/`nym-network-requester` carries authenticated SMTP/TLS
submission to the Virebent MTA. Postfix signs and relays the message to
Mail2News. Mail2News then uses Tor to post to the TCPReset onion NNTP
endpoint. The browser-to-N2Usenet hop remains HTTPS.
## Required Configuration
Set these in an environment file or systemd unit:
```text
N2U_LISTEN=127.0.0.1:8095
N2U_PUBLIC_BASE_URL=https://n2usenet.virebent.art
N2U_SMTP_HOST=51.178.55.22
N2U_SMTP_PORT=587
N2U_SMTP_TLS_SERVER_NAME=mail.virebent.art
N2U_SMTP_IMPLICIT_TLS=false
N2U_SMTP_RECIPIENT=mail2news@mail2news.tcpreset.net
N2U_SMTP_ENVELOPE_FROM=n2usenet@virebent.art
N2U_SMTP_SENDER=n2usenet@virebent.art
N2U_SMTP_USERNAME=n2usenet@virebent.art
N2U_SMTP_PASSWORD_FILE=/etc/n2usenet/smtp-password
N2U_SMTP_HELO=n2usenet.virebent.art
N2U_TRANSPORT_PROBE_INTERVAL=15m
N2U_MESSAGE_ID_DOMAIN=n2usenet.virebent.art
N2U_CSRF_KEY_FILE=/etc/n2usenet/csrf-key
N2U_IDENTICONS_CLI=/usr/local/bin/identicons-cli
N2U_REQUIRE_FACE=true
N2U_NYM_ENABLED=true
N2U_NYM_MANAGED=false
N2U_NYM_BINARY=/opt/n2usenet/bin/nym-socks5-client
N2U_NYM_HOME=/var/lib/n2usenet/nym
N2U_NYM_SOCKS=127.0.0.1:11080
```
Do not commit provider credentials, SMTP credentials, private keys, or operator
secrets. The provider address is deployment configuration.
## Notes
- Hashcash replay protection is memory-only and is not written to disk.
- IP rate limiting uses an in-memory keyed hash and is not persisted.
- Ed25519 signatures are verified server-side when posts are submitted.
- `Face:` is mandatory by default: every accepted identity must produce a VFACE
header from `username|email|ed25519-public-key`.
- The browser still generates/loads the Ed25519 identity and signs messages
locally. The server never receives the Ed25519 secret key.
- Browser identity, message fields, and submission state are kept only in tab
memory. After a successful send, the UI clears the key material and form
inputs immediately.
- SMTP uses a fixed envelope sender by default, `n2usenet@virebent.art`, so the
Mail2News relay does not depend on the user's pseudonymous email passing
remote sender policy checks.
- The RFC 5322 `From:` header publishes the complete profile identity,
`username <email>`. `Sender:` identifies `n2usenet@virebent.art` as the
submitting agent, while SMTP AUTH and the envelope sender remain fixed on
that service account. The profile email is a signed pseudonymous identity
claim, not proof that the user controls its domain.
- SMTP credentials are read from a root-managed file and AUTH is rejected by
the application configuration unless TLS is enabled.
- Production uses the MTA's global IPv4 address as the SOCKS destination while
still verifying `mail.virebent.art` in TLS. This keeps the Nym requester's
non-global-address filter strict when the MTA host resolves its own hostname
to local interface addresses.
- `/submit` returns `Cache-Control: no-store` and the browser path uses fetch
so successful submissions do not leave the full form state in the rendered
response page.
- The CSRF cookie is session-scoped without a fixed elapsed-time expiry. The
browser refreshes the signed token immediately before submission. Production
uses a root-managed signing key so restarts do not invalidate open tabs, and
valid session tokens are reused so multiple tabs cannot rotate each other's
cookie.
- `/healthz` reports only process liveness. `/readyz` reports the cached result
of a background Nym/STARTTLS/SMTP AUTH probe and never creates transport
traffic in response to an HTTP request.
- `n2usenet-gateway-watch.timer` checks the active Nym gateway registration
daily. It rotates only within 24 hours of expiry, verifies the complete SMTP
path without sending mail, and restores the previous gateway database if the
replacement fails.
- The app does not add a clearnet fallback to the M2Usenet onion PHP sender.
- The service now prefers the `N2U_*` environment variable prefix and still
accepts legacy `M2U_*` variables during the rollout.
## Current Production Status
As of 2026-07-13 the standalone service is live on `pietro` and the Nym SMTP
transport is working through a dedicated requester on `victor` and a local
`nym-socks5-client` on `pietro`.
Working deployment shape:
- `victor` and `rasmus` are SSH aliases for the same host, `51.178.55.22`.
- `victor` runs `n2usenet-network-requester.service`.
- `pietro` runs `n2usenet-socks.service` on `127.0.0.1:11080`.
- `pietro` runs `n2usenet.service` with authenticated SMTP submission to
`51.178.55.22:587` through Nym and verifies `mail.virebent.art` in TLS.
- `pietro` uses `n2usenet@virebent.art` as the SMTP envelope sender.
- `victor` Postfix relays to `mail2news@mail2news.tcpreset.net` with the
domain's SPF, DKIM, and DMARC policy.
`identicons-cli` is already available on `victor` at `/usr/local/bin/identicons-cli`.
Its output was checked against the `Ch1ffr3punk/identicons` engine using
multiple deterministic `username|email|pubkey` inputs; the decoded 48x48 PNG
outputs matched byte-for-byte.
Direct SMTP checks from `victor` confirm that `mail2news.tcpreset.net` accepts:
- `25` with STARTTLS.
- `587` with STARTTLS.
- `465` with implicit TLS.
|