ipv6-bridge 1.0.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,33 +1,107 @@
1
1
  # IPv6 Bridge
2
2
 
3
- > Local DNS64/NAT64 proxy for IPv6-only networks — access IPv4 sites seamlessly.
3
+ [![npm version](https://img.shields.io/npm/v/ipv6-bridge.svg)](https://www.npmjs.com/package/ipv6-bridge)
4
+ [![npm downloads](https://img.shields.io/npm/dm/ipv6-bridge.svg)](https://www.npmjs.com/package/ipv6-bridge)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
6
 
5
- IPv4 addresses are exhausted globally. Many ISPs now deploy IPv6-only networks, but millions of websites still only support IPv4. IPv6 Bridge solves this by running a local proxy that translates traffic using DNS64 and NAT64 standards.
7
+ > DNS64-aware HTTP proxy for IPv6-only networks access IPv4 sites seamlessly.
6
8
 
7
- ## Features
9
+ IPv4 addresses are exhausted globally. Many ISPs now deploy IPv6-only networks, but millions of websites still only support IPv4. IPv6 Bridge solves this by running a local application-layer proxy that synthesizes DNS64 addresses and routes HTTP/HTTPS traffic through your ISP's NAT64 gateway.
8
10
 
9
- - **Zero dependencies** pure Node.js, nothing to install
10
- - **Auto-detection** — starts only when needed (IPv6-only network with broken NAT64)
11
- - **HTTP & HTTPS** full proxy support including CONNECT tunneling
12
- - **RFC compliant** — implements RFC 6052 (DNS64) and RFC 6146 (NAT64)
13
- - **Cross-platform** works on Windows, macOS, and Linux
14
- - **Programmatic API** use from your Node.js app or the CLI
11
+ ## Why IPv6 Bridge? (The Advantage)
12
+
13
+ While there are other NAT64/DNS64 bridges out there (like Tayga or Jool), **IPv6 Bridge** occupies a very specific, developer-friendly niche:
14
+
15
+ 1. **100% User-Space & Zero Dependencies**: Most IPv6 bridges require installing complex C++ binaries, compiling Linux kernel modules, or configuring OS-level `TUN/TAP` interfaces. This project runs entirely in user-space using pure Node.js standard libraries. Just run it.
16
+ 2. **It Tells You What's Wrong**: `ipv6-bridge doctor` checks your resolvers, connectivity, NAT64 availability and prefix configuration, then explains each result in plain language. Kernel-level translators can't tell you why your network is broken.
17
+ 3. **Honest About What It Did**: `/status` reports a `translationRate` — the share of traffic that actually went through NAT64. When DNS64 fails and the bridge falls back to a direct connection, it says so, loudly. A bridge that silently stops bridging is worse than one that fails.
18
+ 4. **Intelligent Auto-Detection**: It checks whether IPv4 already works before doing anything, so it stays out of the way on dual-stack networks and only activates when you are genuinely stuck on an IPv6-only network without NAT64.
19
+ 5. **Programmatic API**: Designed for software engineers, it exports a clean `start()` and `stop()` API. You can import this package directly into your automated testing pipelines (like Cypress or Jest) to simulate IPv6 environments during CI/CD builds.
20
+ 6. **Standards Compliant**: Implements every RFC 6052 prefix length (`/32` through `/96`), verified against the RFC's own test vectors, discovers your network's real prefix via RFC 7050, and honours the section 3.1 rule that the well-known prefix must never carry non-global IPv4 addresses.
21
+
22
+ ## Production Features
23
+
24
+ | Capability | How |
25
+ |-----------|-----|
26
+ | Any TCP protocol (ssh, git, databases) | SOCKS5 listener — `IPV6_BRIDGE_SOCKS_PORT=1080` |
27
+ | Automatic prefix configuration | RFC 7050 discovery via `ipv4only.arpa` |
28
+ | Observability | `/status`, `/metrics` (Prometheus), `/healthz` |
29
+ | Client onboarding | `/proxy.pac` auto-configuration file |
30
+ | Access control | `IPV6_BRIDGE_AUTH`, `IPV6_BRIDGE_ALLOW` |
31
+ | Performance | DNS caching, keep-alive connection pooling |
32
+ | Reliability | Failover across candidate addresses |
33
+ | Split routing | `IPV6_BRIDGE_BYPASS=*.internal.company.com` |
15
34
 
16
35
  ## Quick Start
17
36
 
18
- ### CLI
37
+ **New here? Start with [docs/GUIDE.md](docs/GUIDE.md)** — it covers when you need this, how to connect your applications, and worked examples.
38
+
39
+ ### 1. Find out whether you need it
40
+
41
+ ```bash
42
+ npx ipv6-bridge doctor
43
+ ```
44
+
45
+ This checks your resolvers, IPv4/IPv6 reachability and whether a NAT64 gateway exists, then explains each result.
46
+
47
+ ### 2. Start it
19
48
 
20
49
  ```bash
21
50
  npx ipv6-bridge start
22
51
  ```
23
52
 
24
- The bridge auto-detects whether it's needed. To force it:
53
+ The bridge auto-detects whether it's needed and exits quietly if it isn't — so it's safe to run anywhere. To run it anyway (to test or demo):
25
54
 
26
55
  ```bash
27
56
  FORCE_BRIDGE=1 npx ipv6-bridge start
28
57
  ```
29
58
 
30
- ### Programmatic
59
+ ### 3. Point an application at it
60
+
61
+ Nothing routes through the proxy automatically — that's the most common point of confusion.
62
+
63
+ ```bash
64
+ curl -x http://127.0.0.1:8080 https://example.com
65
+ ```
66
+
67
+ For browsers, use the auto-config URL `http://127.0.0.1:8080/proxy.pac`. See the [guide](docs/GUIDE.md#4-connecting-your-applications) for npm, Docker, ssh, git and more.
68
+
69
+ ### 4. Confirm it's actually translating
70
+
71
+ ```bash
72
+ npx ipv6-bridge status
73
+ ```
74
+
75
+ ### Use it inside your application (no proxy, no system config)
76
+
77
+ If you don't want to run a proxy at all, drop the bridge straight into your app's
78
+ outbound connections:
79
+
80
+ ```bash
81
+ npm i ipv6-bridge
82
+ ```
83
+
84
+ ```javascript
85
+ const { createHttpsAgent } = require('ipv6-bridge');
86
+ const agent = createHttpsAgent();
87
+
88
+ // Connects over native IPv6 when possible, through NAT64 when translation is
89
+ // needed, and over IPv4 as a last resort — without any system configuration.
90
+ https.get('https://some-ipv4-only-api.example', { agent }, handleResponse);
91
+ ```
92
+
93
+ Works with anything that accepts an agent (axios, got, node-fetch) or a `lookup`
94
+ function (`net.connect`, `http.request`). For Node's global `fetch`, use
95
+ `createConnector()` with undici.
96
+
97
+ ```javascript
98
+ const { getStats } = require('ipv6-bridge');
99
+ getStats().translationRate; // did translation actually happen?
100
+ ```
101
+
102
+ See [Using it from Node.js](docs/GUIDE.md#7-using-it-from-nodejs) for the full set.
103
+
104
+ ### Run it as a proxy
31
105
 
32
106
  ```javascript
33
107
  const { start, stop } = require('ipv6-bridge');
@@ -35,22 +109,15 @@ const { start, stop } = require('ipv6-bridge');
35
109
  const server = await start(8080);
36
110
  // → returns the server, or null if bridge isn't needed
37
111
 
38
- // Later:
39
112
  await stop();
40
113
  ```
41
114
 
42
- ### Install as a Dependency
43
-
44
- ```bash
45
- npm install ipv6-bridge
46
- ```
47
-
48
115
  ## How It Works
49
116
 
50
117
  **The "Language Translator" Analogy**
51
118
  > Imagine you only speak English (IPv6), but you need to call a business in Japan where they only speak Japanese (IPv4). If you call them directly, you won't understand each other.
52
- >
53
- > This project acts like a live, bilingual phone operator sitting right next to you. When you try to make the call, the software intercepts it, looks up the Japanese translation for the phone number (**DNS64**), and then acts as a middleman translating your English sentences into Japanese and back again in real-time (**NAT64 proxy**). The result is that you have a seamless conversation without even realizing a translation is happening.
119
+ >
120
+ > This project acts like a live, bilingual phone operator sitting right next to you. When you try to make the call, the software intercepts it, looks up the Japanese translation for the phone number (**DNS64**), and then acts as a middleman translating your English sentences into Japanese and back again in real-time (**application-layer proxy**). The result is that you have a seamless conversation without even realizing a translation is happening.
54
121
 
55
122
  ### Technical Flow
56
123
 
@@ -67,30 +134,95 @@ Your App → HTTP request → IPv6 Bridge (localhost:8080)
67
134
  IPv4 Internet (google.com)
68
135
  ```
69
136
 
70
- 1. **Detection** — checks if you're on an IPv6-only network
71
- 2. **DNS64** — resolves hostnames; if only an IPv4 address exists, synthesizes an IPv6 address using the NAT64 prefix (`64:ff9b::`)
137
+ 1. **Detection** — checks whether IPv4 already works, whether IPv6 works, and whether your ISP already provides NAT64
138
+ 2. **DNS64** — resolves hostnames through the system resolver; if only an IPv4 address exists, synthesizes an IPv6 address using the NAT64 prefix (`64:ff9b::`)
72
139
  3. **Proxy** — routes HTTP/HTTPS through IPv6; the ISP's NAT64 gateway translates to IPv4
73
140
  4. **Response** — data flows back through the same path, transparently
74
141
 
75
- For a deep dive, see [ARCHITECTURE.md](ARCHITECTURE.md).
142
+ For a deep dive, see [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).
76
143
 
77
144
  ## Configuration
78
145
 
79
146
  | Environment Variable | Default | Description |
80
147
  |---------------------|---------|-------------|
81
148
  | `IPV6_BRIDGE_PORT` | `8080` | Proxy listen port |
149
+ | `IPV6_BRIDGE_HOST` | `127.0.0.1` | Interface to bind to |
150
+ | `IPV6_BRIDGE_SOCKS_PORT` | _(off)_ | Serve SOCKS5 on this port |
151
+ | `IPV6_BRIDGE_AUTH` | _(none)_ | Require `user:password` from clients |
152
+ | `IPV6_BRIDGE_ALLOW` | _(any)_ | Client allowlist, e.g. `192.168.1.0/24` |
153
+ | `IPV6_BRIDGE_BYPASS` | _(none)_ | Hosts to reach directly, e.g. `*.internal.com` |
154
+ | `IPV6_BRIDGE_CONTROL` | `on` | Serve `/healthz`, `/status`, `/metrics`, `/proxy.pac` |
155
+ | `IPV6_BRIDGE_DISCOVER_PREFIX` | `on` | Discover the NAT64 prefix via RFC 7050 |
82
156
  | `FORCE_BRIDGE` | _(unset)_ | Start even if not needed |
83
- | `NAT64_PREFIX` | `64:ff9b::` | Custom NAT64 prefix |
157
+ | `NAT64_PREFIX` | `64:ff9b::/96` | NAT64 prefix, with optional `/length` |
158
+ | `IPV6_DNS_TIMEOUT` | `5000` | DNS resolution timeout (ms) |
159
+ | `IPV6_DNS_CACHE_TTL` | `30000` | DNS cache entry lifetime (ms) |
160
+ | `IPV6_CONN_TIMEOUT` | `10000` | Proxy connection timeout (ms) |
161
+ | `IPV4_TEST_URL` | `http://ipv4.google.com` | Endpoint used to detect working IPv4 |
162
+ | `IPV6_TEST_URL` | `http://ipv6.google.com` | Endpoint used to detect working IPv6 |
163
+ | `NAT64_TEST_HOST` | `ipv4.google.com` | IPv4-only host used to probe for NAT64 |
164
+ | `LOG_LEVEL` | `info` | Log verbosity (`silent`, `error`, `warn`, `info`, `debug`) |
165
+
166
+ See [docs/API.md](docs/API.md) for the complete list. Invalid values (a malformed `NAT64_PREFIX`, a port outside 1–65535) fail immediately at startup with a clear message rather than surfacing later as unexplainable connection errors.
167
+
168
+ ## Diagnosing a network
169
+
170
+ ```bash
171
+ npx ipv6-bridge doctor
172
+ ```
173
+
174
+ Reports whether your resolvers agree, whether IPv4/IPv6/NAT64 are reachable, which NAT64 prefix your network advertises versus the one configured, and whether the listener is exposed. Exits non-zero on failure, so it works in provisioning scripts.
175
+
176
+ ## Monitoring
177
+
178
+ With the bridge running:
179
+
180
+ ```bash
181
+ curl http://127.0.0.1:8080/status # JSON: counters, routes, DNS cache
182
+ curl http://127.0.0.1:8080/metrics # Prometheus exposition format
183
+ curl http://127.0.0.1:8080/healthz # liveness probe
184
+ ```
185
+
186
+ The field that matters most is `translationRate` — the share of connections routed through NAT64. If it sits at `0` while `routes.directIpv4Fallback` climbs, the bridge is passing traffic through untranslated, and `doctor` will tell you why.
187
+
188
+ ## Non-HTTP protocols
189
+
190
+ The HTTP proxy only carries HTTP. For ssh, git, database clients and anything else over TCP, enable the SOCKS5 listener:
191
+
192
+ ```bash
193
+ IPV6_BRIDGE_SOCKS_PORT=1080 npx ipv6-bridge start
194
+
195
+ git config --global http.proxy socks5h://127.0.0.1:1080
196
+ ssh -o ProxyCommand='nc -X 5 -x 127.0.0.1:1080 %h %p' user@host
197
+ ```
198
+
199
+ ## Security
200
+
201
+ The proxy binds to `127.0.0.1` by default so that only processes on your own machine can use it, and it performs no authentication unless you configure some.
202
+
203
+ Binding to a routable interface turns your machine into an open relay that anyone on the same network can send traffic through, attributed to your IP address. If you do expose it, pair that with access control — the bridge warns at startup if you don't:
204
+
205
+ ```bash
206
+ IPV6_BRIDGE_HOST=0.0.0.0 \
207
+ IPV6_BRIDGE_AUTH=user:secret \
208
+ IPV6_BRIDGE_ALLOW=192.168.1.0/24 \
209
+ npx ipv6-bridge start
210
+ ```
211
+
212
+ Credentials are required on the HTTP, CONNECT and SOCKS5 paths alike. `/healthz` stays reachable without them so load balancers keep working.
84
213
 
85
214
  ## API
86
215
 
87
- ### `start(port?): Promise<http.Server | null>`
216
+ ### `start(port?, options?): Promise<http.Server | null>`
88
217
 
89
218
  Starts the proxy. Returns the server instance, or `null` if the bridge isn't needed.
90
219
 
220
+ - `options.host` — interface to bind to (defaults to `127.0.0.1`)
221
+ - `options.force` — start even if detection says the bridge isn't needed
222
+
91
223
  ### `stop(): Promise<void>`
92
224
 
93
- Stops the running bridge.
225
+ Stops the running bridge and tears down live connections, including open CONNECT tunnels.
94
226
 
95
227
  See [docs/API.md](docs/API.md) for the full API reference.
96
228
 
@@ -100,13 +232,15 @@ See [docs/API.md](docs/API.md) for the full API reference.
100
232
  npm test
101
233
  ```
102
234
 
235
+ The suite runs entirely against local servers and needs no network access.
236
+
103
237
  ### Demo Application
104
238
 
105
239
  An interactive diagnostics tool:
106
240
 
107
241
  ```bash
108
- cd demo-app && npm start
109
- # Open http://localhost:3000
242
+ npm run demo
243
+ # Open http://127.0.0.1:3000
110
244
  ```
111
245
 
112
246
  ### Dual-Stack Test Server
@@ -124,11 +258,20 @@ See [test-server/README.md](test-server/README.md) for details.
124
258
  ```
125
259
  src/
126
260
  cli.js CLI entry point
127
- config.js Configuration constants
261
+ config.js Configuration and validation
262
+ connect.js Outbound connections, failover, pooling
128
263
  detect.js Network detection
264
+ discovery.js NAT64 prefix discovery (RFC 7050)
129
265
  dns64.js DNS64 resolver
266
+ doctor.js Diagnostics
267
+ cache.js Bounded TTL cache
130
268
  index.js Public API (start/stop)
269
+ ipv6.js IPv6 and RFC 6052 address primitives
270
+ logger.js Structured logger
271
+ netmatch.js CIDR and hostname matching
131
272
  proxy.js HTTP/HTTPS proxy
273
+ socks5.js SOCKS5 server
274
+ stats.js Runtime counters
132
275
  tests/ Test suite
133
276
  demo-app/ Interactive demo
134
277
  test-server/ Dual-stack test server
@@ -136,15 +279,47 @@ examples/ Usage examples
136
279
  docs/ Extended documentation
137
280
  ```
138
281
 
282
+ ## Limitations
283
+
284
+ This project is an **application-layer proxy**, not a packet-level NAT64 implementation. Be aware of the following:
285
+
286
+ - **Not transparent** — applications must be configured to use the proxy. System services, games, and mobile apps won't route through it automatically. `/proxy.pac` helps for browsers; SOCKS5 helps for everything else.
287
+ - **TCP only** — SOCKS5 covers arbitrary TCP, but UDP (`UDP ASSOCIATE`) and inbound `BIND` are not implemented, as neither is possible from user space without inbound reachability.
288
+ - **No HTTP/2 or HTTP/3 to the origin** — upstream requests are HTTP/1.1. Clients still negotiate whatever they like inside a CONNECT tunnel, so HTTPS is unaffected.
289
+ - **Requires an upstream NAT64 gateway** — this project synthesizes DNS64 addresses but relies on your network's NAT64 infrastructure for the actual packet translation. `doctor` tells you whether one exists.
290
+ - **Private addresses are not translated** — RFC 6052 section 3.1 forbids carrying non-global IPv4 addresses over the well-known prefix, so targets like `127.0.0.1` or `192.168.x.x` are connected to directly over IPv4 instead.
291
+ - **DNS cache uses a fixed TTL** — the system resolver does not expose record TTLs, so cached entries expire on `IPV6_DNS_CACHE_TTL` (30s) rather than the DNS TTL.
292
+
293
+ ## Roadmap
294
+
295
+ We have an extensive roadmap planned for future releases, including DNS caching, SOCKS5 support, and Happy Eyeballs (RFC 8305).
296
+
297
+ See [docs/ROADMAP.md](docs/ROADMAP.md) for the full breakdown of planned features and protocol expansions.
298
+
299
+ ## Documentation
300
+
301
+ | Document | What's in it |
302
+ |----------|--------------|
303
+ | [docs/GUIDE.md](docs/GUIDE.md) | **Start here.** When to use it, connecting applications, worked scenarios, troubleshooting, glossary |
304
+ | [docs/API.md](docs/API.md) | Programmatic API, every environment variable, operational endpoints |
305
+ | [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | How it works internally and why the design choices were made |
306
+ | [docs/ROADMAP.md](docs/ROADMAP.md) | What has shipped and what is planned |
307
+ | [docs/CHANGELOG.md](docs/CHANGELOG.md) | Release history |
308
+ | [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) | How to work on the project |
309
+
310
+ `ipv6-bridge --help` lists every command, option and endpoint.
311
+
139
312
  ## Standards
140
313
 
141
314
  - [RFC 6052](https://tools.ietf.org/html/rfc6052) — IPv6 Addressing of IPv4/IPv6 Translators
142
315
  - [RFC 6146](https://tools.ietf.org/html/rfc6146) — Stateful NAT64
143
316
  - [RFC 6147](https://tools.ietf.org/html/rfc6147) — DNS64
317
+ - [RFC 6890](https://tools.ietf.org/html/rfc6890) — Special-Purpose IP Address Registries
318
+ - [RFC 7230](https://tools.ietf.org/html/rfc7230) — HTTP/1.1 Message Syntax and Routing
144
319
 
145
320
  ## Contributing
146
321
 
147
- See [CONTRIBUTING.md](CONTRIBUTING.md).
322
+ See [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md).
148
323
 
149
324
  ## License
150
325