summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AGENTS.md12
-rw-r--r--README.md26
-rw-r--r--deploy/README.md27
-rw-r--r--deploy/postfix/diego-master.cf.fragment12
-rw-r--r--deploy/postfix/m2usenet-ingress1
-rw-r--r--deploy/postfix/victor-master.cf.fragment13
-rw-r--r--deploy/postfix/victor-transport.fragment3
-rw-r--r--deploy/tor/.gitignore2
-rw-r--r--deploy/tor/diego-torrc.fragment4
-rw-r--r--deploy/tor/victor-torrc.fragment7
-rw-r--r--send.php20
11 files changed, 107 insertions, 20 deletions
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..e4c647c
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,12 @@
+# Repository guidance
+
+- Use the Gab Virebent identity for this repository and its Virebent remote.
+- Commit and push tested source and deployment fragments to
+ `git.virebent.art/virebent/m2usenet-and-mail2news` before changing
+ production.
+- Do not commit Tor client-authorization entries, private keys, credentials,
+ message contents, or production logs.
+- Keep the integrated M2Usenet path Onion-only. Do not add a clearnet fallback.
+- Treat SMTP `250` as relay acceptance, not proof of final NNTP publication.
+- Hidden services must terminate on dedicated restricted listeners, never on
+ a Postfix listener that trusts loopback through `mynetworks`.
diff --git a/README.md b/README.md
index 4e555f3..06fb6a3 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
**Privacy-focused Usenet posting system with authentication preprocessing**
-m2usenet is a secure, privacy-oriented web interface for posting to Usenet newsgroups. The system preprocesses messages with cryptographic authentication (Hashcash + Ed25519) before forwarding them to external mail2news gateways, featuring automatic fallback between .onion and clearnet gateways.
+m2usenet is a secure, privacy-oriented web interface for posting to Usenet newsgroups. The system preprocesses messages with cryptographic authentication (Hashcash + Ed25519) before forwarding them through Tor to a private Mail2News onion ingress.
## 🏗️ Architecture
@@ -15,7 +15,7 @@ m2usenet is a secure, privacy-oriented web interface for posting to Usenet newsg
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
```
-**Flow:** Web UI → Local sendmail → m2usenet preprocessor → External mail2news gateway → Usenet
+**Current integrated flow:** Web UI → Tor → private Mail2News onion ingress → Mail2News → Tor/onion NNTP → Usenet
## 🔐 Security Features
@@ -23,14 +23,21 @@ m2usenet is a secure, privacy-oriented web interface for posting to Usenet newsg
- **Ed25519 Digital Signatures**: Cryptographic message authentication
- **Tor Integration**: Primary routing through .onion networks
- **No Data Collection**: Zero access logs, no tracking
-- **Automatic Fallback**: .onion → clearnet gateway redundancy
+- **Private SMTP ingress**: Tor v3 client authorization and restricted Postfix recipient policy
## 🌐 Gateway Configuration
-| Priority | Gateway | Description |
-|----------|---------|-------------|
-| **Primary** | `mail2news@xilb7y4kj6u6qfo45o3yk2kilfv54ffukzei3puonuqlncy7cn2afwyd.onion` | Via Tor for privacy |
-| **Fallback** | `mail2news@mail2news.tcpreset.net` | Clearnet for reliability |
+| Role | Gateway | Description |
+|------|---------|-------------|
+| **Primary and retry** | `mail2news@xilb7y4kj6u6qfo45o3yk2kilfv54ffukzei3puonuqlncy7cn2afwyd.onion` | Private Onion ingress reached through Tor |
+
+There is no clearnet fallback in the integrated Onion Newsreader path. SMTP
+acceptance means that the private relay queued the message; final NNTP
+publication is asynchronous.
+
+The restricted Tor and Postfix deployment fragments are documented in
+[`deploy/`](deploy/README.md). Authorization keys are deployment secrets and
+must never be committed.
## 📋 Requirements
@@ -98,8 +105,8 @@ sudo chmod 755 /var/www/m2usenet /var/log/m2usenet /home/m2usenet
```bash
# Clone repository (or download files)
cd /tmp
-git clone https://github.com/your-repo/m2usenet.git
-cd m2usenet
+git clone ssh://git@git.virebent.art:2223/virebent/m2usenet-and-mail2news.git
+cd m2usenet-and-mail2news
# Copy web frontend
sudo cp index.php send.php powWorker.js /var/www/m2usenet/
@@ -352,4 +359,3 @@ Contributions are welcome! Please read CONTRIBUTING.md for guidelines.
**m2usenet v1.0.0** - Privacy-focused Usenet posting for the modern era
-
diff --git a/deploy/README.md b/deploy/README.md
new file mode 100644
index 0000000..5046bb5
--- /dev/null
+++ b/deploy/README.md
@@ -0,0 +1,27 @@
+# Private M2Usenet onion ingress
+
+The integrated M2Usenet sender connects through Tor directly to the Mail2News
+onion service. The production hidden service uses Tor v3 client authorization
+and terminates on a dedicated loopback-only Postfix listener.
+
+Apply the fragments from this directory through the normal configuration
+management or deployment process. They are intentionally not complete server
+configuration files.
+
+Deployment order:
+
+1. Generate a Tor v3 client-authorization key pair outside the repository.
+2. Install the public authorization entry in the hidden service's
+ `authorized_clients` directory on the Mail2News host.
+3. Install the private authorization entry in `ClientOnionAuthDir` on the
+ M2Usenet host, mode `0600`, readable only by the Tor service account.
+4. Install and compile the Postfix maps, then validate Postfix.
+5. Validate Tor configuration and reload both services.
+6. Test unauthorized connection rejection and recipient restrictions before
+ deploying `send.php`.
+7. Deploy the committed application revision and verify final NNTP
+ publication with a controlled article.
+
+Never commit either authorization entry. A Tor hidden-service connection
+arrives from loopback, so it must never be forwarded to a Postfix listener
+that grants relay permission to `mynetworks`.
diff --git a/deploy/postfix/diego-master.cf.fragment b/deploy/postfix/diego-master.cf.fragment
new file mode 100644
index 0000000..2a2e1d5
--- /dev/null
+++ b/deploy/postfix/diego-master.cf.fragment
@@ -0,0 +1,12 @@
+# Dedicated ingress for the private Mail2News onion hidden service.
+127.0.0.1:2526 inet n - n - 4 smtpd
+ -o syslog_name=postfix/m2usenet-onion
+ -o myhostname=xilb7y4kj6u6qfo45o3yk2kilfv54ffukzei3puonuqlncy7cn2afwyd.onion
+ -o smtpd_tls_security_level=none
+ -o smtpd_sasl_auth_enable=no
+ -o smtpd_relay_restrictions=reject_unauth_destination
+ -o smtpd_recipient_restrictions=check_recipient_access,hash:/etc/postfix/m2usenet-ingress,reject
+ -o smtpd_reject_unlisted_recipient=yes
+ -o smtpd_helo_required=yes
+ -o smtpd_recipient_limit=1
+ -o message_size_limit=131072
diff --git a/deploy/postfix/m2usenet-ingress b/deploy/postfix/m2usenet-ingress
new file mode 100644
index 0000000..fb42230
--- /dev/null
+++ b/deploy/postfix/m2usenet-ingress
@@ -0,0 +1 @@
+mail2news@xilb7y4kj6u6qfo45o3yk2kilfv54ffukzei3puonuqlncy7cn2afwyd.onion OK
diff --git a/deploy/postfix/victor-master.cf.fragment b/deploy/postfix/victor-master.cf.fragment
new file mode 100644
index 0000000..9012438
--- /dev/null
+++ b/deploy/postfix/victor-master.cf.fragment
@@ -0,0 +1,13 @@
+# Restricted target for the legacy qee4 hidden service. Do not forward it to
+# the ordinary SMTP listener, which may trust loopback through mynetworks.
+127.0.0.1:2527 inet n - n - 4 smtpd
+ -o syslog_name=postfix/qee-onion
+ -o myhostname=qee4i7sags6phsvb2yodwecfj7noimfhhalsjktsvikrwotxzis3raad.onion
+ -o smtpd_tls_security_level=none
+ -o smtpd_sasl_auth_enable=no
+ -o smtpd_relay_restrictions=reject_unauth_destination
+ -o smtpd_recipient_restrictions=reject_unauth_destination
+ -o smtpd_reject_unlisted_recipient=yes
+ -o smtpd_helo_required=yes
+ -o smtpd_recipient_limit=1
+ -o message_size_limit=131072
diff --git a/deploy/postfix/victor-transport.fragment b/deploy/postfix/victor-transport.fragment
new file mode 100644
index 0000000..cf7d820
--- /dev/null
+++ b/deploy/postfix/victor-transport.fragment
@@ -0,0 +1,3 @@
+# Exact lookup is required; relying only on a parent .onion key can select the
+# ordinary SMTP transport depending on Postfix parent-domain matching policy.
+xilb7y4kj6u6qfo45o3yk2kilfv54ffukzei3puonuqlncy7cn2afwyd.onion smtptor:
diff --git a/deploy/tor/.gitignore b/deploy/tor/.gitignore
new file mode 100644
index 0000000..e2124bd
--- /dev/null
+++ b/deploy/tor/.gitignore
@@ -0,0 +1,2 @@
+*.auth
+*.auth_private
diff --git a/deploy/tor/diego-torrc.fragment b/deploy/tor/diego-torrc.fragment
new file mode 100644
index 0000000..71847d6
--- /dev/null
+++ b/deploy/tor/diego-torrc.fragment
@@ -0,0 +1,4 @@
+# Client authorization entries are generated and installed outside Git under:
+# /var/lib/tor/mail/authorized_clients/
+HiddenServiceDir /var/lib/tor/mail/
+HiddenServicePort 25 127.0.0.1:2526
diff --git a/deploy/tor/victor-torrc.fragment b/deploy/tor/victor-torrc.fragment
new file mode 100644
index 0000000..b687f43
--- /dev/null
+++ b/deploy/tor/victor-torrc.fragment
@@ -0,0 +1,7 @@
+# The private client authorization entry is generated and installed outside
+# Git under this directory with mode 0600.
+ClientOnionAuthDir /var/lib/tor/onion_auth
+
+# Keep the legacy qee4 service isolated from the ordinary SMTP listener.
+HiddenServiceDir /var/lib/tor/Mail/
+HiddenServicePort 25 127.0.0.1:2527
diff --git a/send.php b/send.php
index 36e93b0..bb00986 100644
--- a/send.php
+++ b/send.php
@@ -19,17 +19,17 @@ ini_set('max_execution_time', 180);
// SMTP Relay Configuration
define('PRIMARY_RELAY', [
- 'host' => 'qee4i7sags6phsvb2yodwecfj7noimfhhalsjktsvikrwotxzis3raad.onion',
+ 'host' => 'xilb7y4kj6u6qfo45o3yk2kilfv54ffukzei3puonuqlncy7cn2afwyd.onion',
'port' => 25,
'mail2news' => 'mail2news@xilb7y4kj6u6qfo45o3yk2kilfv54ffukzei3puonuqlncy7cn2afwyd.onion',
- 'name' => 'qee4-primary'
+ 'name' => 'mail2news-onion-primary'
]);
define('FALLBACK_RELAY', [
'host' => 'xilb7y4kj6u6qfo45o3yk2kilfv54ffukzei3puonuqlncy7cn2afwyd.onion',
'port' => 25,
'mail2news' => 'mail2news@xilb7y4kj6u6qfo45o3yk2kilfv54ffukzei3puonuqlncy7cn2afwyd.onion',
- 'name' => 'smtp-fallback'
+ 'name' => 'mail2news-onion-retry'
]);
// Security Configuration
@@ -147,7 +147,7 @@ function sendMessage($data) {
}
if ($result['success']) {
- secureLog("Message delivered successfully via {$relay['name']} relay");
+ secureLog("Message accepted successfully by {$relay['name']} relay");
} else {
secureLog("Message delivery failed on both PRIMARY and FALLBACK relays", 'ERROR');
}
@@ -892,13 +892,13 @@ function sendViaNativePHPSMTP($data, $smtpRelay, $smtpPort, $mail2newsAddress) {
@smtpSendCommand($socket, "QUIT\r\n", 221);
$totalTime = microtime(true) - $startTime;
- secureLog(sprintf("=== Message delivered successfully in %.2fs ===", $totalTime));
+ secureLog(sprintf("=== Message accepted by relay in %.2fs ===", $totalTime));
fclose($socket);
return [
'success' => true,
- 'message' => 'Message sent via secure onion gateway',
+ 'message' => 'Message accepted by the private Mail2News onion relay',
'messageId' => $messageId,
'gateway' => $mail2newsAddress
];
@@ -954,7 +954,7 @@ function successResponse($messageId, $gateway) {
<!DOCTYPE html>
<html>
<head>
- <title>Message Sent</title>
+ <title>Message Accepted</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@@ -974,14 +974,14 @@ function successResponse($messageId, $gateway) {
<body>
<div class="container">
<div class="success">
- <h2>✓ Message Sent</h2>
+ <h2>✓ Message Accepted</h2>
<p><strong>Message-ID:</strong></p>
<div class="message-id"><?php echo htmlspecialchars($messageId); ?></div>
- <p>Your message has been successfully delivered to the Usenet network.</p>
+ <p>Your message has been accepted by the private Mail2News onion relay for asynchronous posting to Usenet.</p>
<div class="info">
<p><strong>Gateway:</strong> <?php echo htmlspecialchars($gateway); ?></p>
<p><small>Message routed via secure Tor SOCKS5 with PHP native implementation</small></p>
- <p><small>Strategy: fog:25 primary → smtp:25 fallback</small></p>
+ <p><small>Strategy: private Mail2News onion:25 with one retry</small></p>
</div>
<p><a href="index.php">Send another message</a></p>
</div>