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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
|
// Copyright (c) 2026 Bitflash developers
// Distributed under the MIT/X11 software license.
//
// Transparent anonymous tunnel. See btftunnel.h.
#include "btftunnel.h"
#include "btfchan.h"
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
typedef int SOCKET;
#ifndef INVALID_SOCKET
#define INVALID_SOCKET (-1)
#endif
#define closesocket(s) ::close(s)
#ifndef SD_BOTH
#define SD_BOTH SHUT_RDWR
#endif
#endif
#include "sockcount.h"
#include <cstring>
#include <cstdio>
#include <vector>
#include <thread>
#include <system_error>
namespace btf
{
bool TunnelInit()
{
return RvInit() && ChanInit();
}
// Create a connected loopback socket pair (no socketpair() on Windows).
// Returns app end and pump end; both are ordinary full-duplex TCP sockets.
static bool MakeLocalPair(btf_socket_t& appEnd, btf_socket_t& pumpEnd)
{
SOCKET listener = BtfSocketTag(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP), SOCK_PAIR_LISTEN);
if (listener == INVALID_SOCKET) return false;
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = 0; // ephemeral
if (bind(listener, (struct sockaddr*)&addr, sizeof(addr)) != 0) { BtfCloseSocket(listener); return false; }
if (listen(listener, 1) != 0) { BtfCloseSocket(listener); return false; }
#ifdef _WIN32
int len = sizeof(addr);
#else
socklen_t len = sizeof(addr);
#endif
if (getsockname(listener, (struct sockaddr*)&addr, &len) != 0) { BtfCloseSocket(listener); return false; }
SOCKET a = BtfSocketTag(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP), SOCK_PAIR_APP);
if (a == INVALID_SOCKET) { BtfCloseSocket(listener); return false; }
if (connect(a, (struct sockaddr*)&addr, sizeof(addr)) != 0) { BtfCloseSocket(a); BtfCloseSocket(listener); return false; }
SOCKET b = BtfSocketTag(accept(listener, NULL, NULL), SOCK_PAIR_PUMP);
BtfCloseSocket(listener);
if (b == INVALID_SOCKET) { BtfCloseSocket(a); return false; }
appEnd = a;
pumpEnd = b;
return true;
}
static bool SockReadN(SOCKET s, void* buf, int n)
{
char* p = (char*)buf; int off = 0;
while (off < n) { int r = recv(s, p + off, n - off, 0); if (r <= 0) return false; off += r; }
return true;
}
static bool SockWriteN(SOCKET s, const void* buf, int n)
{
const char* p = (const char*)buf; int off = 0;
while (off < n) { int r = send(s, p + off, n - off, 0); if (r <= 0) return false; off += r; }
return true;
}
// Outbound pump: plaintext from the app -> echan frame -> rendezvous socket.
static void PumpOut(SOCKET pumpEnd, RvSocket rv, std::vector<unsigned char> key)
{
char buf[16 * 1024];
for (;;)
{
int r = recv(pumpEnd, buf, sizeof(buf), 0);
if (r <= 0) break;
std::vector<unsigned char> frame = ChanEncryptFrame(key.data(), (const unsigned char*)buf, r);
if (!RvWriteN(rv, frame.data(), (int)frame.size())) break;
}
// Tear down: unblock the inbound pump and the app.
shutdown((SOCKET)rv, SD_BOTH);
shutdown(pumpEnd, SD_BOTH);
}
// Inbound pump: echan frames from the rendezvous socket -> plaintext to the app.
static void PumpIn(SOCKET pumpEnd, RvSocket rv, std::vector<unsigned char> key)
{
for (;;)
{
unsigned char len[4];
if (!RvReadN(rv, len, 4)) break;
size_t n = ((size_t)len[0]<<24)|((size_t)len[1]<<16)|((size_t)len[2]<<8)|len[3];
if (n < (size_t)(CHAN_NONCEBYTES + CHAN_MACBYTES) || n > (1u<<20)) break;
std::vector<unsigned char> body(n);
if (!RvReadN(rv, body.data(), (int)n)) break;
std::vector<unsigned char> pt;
if (!ChanDecryptBody(key.data(), body.data(), (int)n, pt)) break; // auth fail -> drop
if (!pt.empty() && !SockWriteN(pumpEnd, pt.data(), (int)pt.size())) break;
}
shutdown(pumpEnd, SD_BOTH);
shutdown((SOCKET)rv, SD_BOTH);
}
// Start the two pumps and hand back the app-facing socket. When both pumps
// finish, close the pump end and the rendezvous socket.
//
// Every tunnel is two threads, and a tunnel is one peer connection (a .btf
// dial or accept, a pool miner, a participant's pool session) -- so the
// thread count scales with peer count, which is attacker-influenced. When
// pthread_create is refused std::thread throws std::system_error; uncaught it
// reached std::terminate and took the whole process down over one connection
// it could not serve. Both spawns are guarded, and the failure paths return
// INVALID_SOCKET, which every caller already handles by dropping just that
// connection.
static btf_socket_t StartTunnel(RvSocket rv, const unsigned char shared[32])
{
btf_socket_t appEnd, pumpEnd;
if (!MakeLocalPair(appEnd, pumpEnd)) { RvClose(rv); return INVALID_SOCKET; }
std::vector<unsigned char> key(shared, shared + 32);
// The inbound pump starts first because it owns the cleanup: it closes
// pumpEnd and rv when it exits. That ownership is what makes the second
// spawn's failure path below race-free.
try
{
std::thread([pumpEnd, rv, key]() {
PumpIn(pumpEnd, rv, key);
BtfCloseSocket(pumpEnd);
RvClose(rv);
}).detach();
}
catch (const std::system_error& e)
{
// Nothing is running yet, so closing everything here is safe.
fprintf(stderr, "btf tunnel: cannot spawn inbound pump (%s), tunnel dropped\n",
e.what());
BtfCloseSocket(pumpEnd);
BtfCloseSocket(appEnd);
RvClose(rv);
return INVALID_SOCKET;
}
try
{
std::thread(PumpOut, pumpEnd, rv, key).detach();
}
catch (const std::system_error& e)
{
// The inbound pump is parked in RvReadN(rv). shutdown() wakes it, and
// it closes pumpEnd and rv itself -- closing them here instead would
// race exactly that, and a reused descriptor is how an unrelated
// socket gets closed.
fprintf(stderr, "btf tunnel: cannot spawn outbound pump (%s), tunnel dropped\n",
e.what());
shutdown((SOCKET)rv, SD_BOTH);
BtfCloseSocket(appEnd);
return INVALID_SOCKET;
}
return appEnd;
}
btf_socket_t BtfClientTunnel(const char* meeting_host, unsigned short port,
const unsigned char target_pubkey[32],
const unsigned char service_enc_pub[32])
{
if (!TunnelInit()) return INVALID_SOCKET;
RvSocket rv = RvClientConnect(meeting_host, port, target_pubkey);
if (rv == RV_INVALID) return INVALID_SOCKET;
unsigned char eph_pub[32], shared[32];
if (!ChanClientHandshake(service_enc_pub, eph_pub, shared)) { RvClose(rv); return INVALID_SOCKET; }
if (!RvWriteN(rv, eph_pub, 32)) { RvClose(rv); return INVALID_SOCKET; }
return StartTunnel(rv, shared);
}
btf_socket_t BtfServiceWrap(RvSocket rv, const unsigned char my_enc_sk[32])
{
if (!TunnelInit()) { RvClose(rv); return INVALID_SOCKET; }
unsigned char eph_pub[32], shared[32];
if (!RvReadN(rv, eph_pub, 32)) { RvClose(rv); return INVALID_SOCKET; }
if (!ChanEndpointHandshake(eph_pub, my_enc_sk, shared)) { RvClose(rv); return INVALID_SOCKET; }
return StartTunnel(rv, shared);
}
} // namespace btf
|