exposr 0.5.2__tar.gz

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.
exposr-0.5.2/PKG-INFO ADDED
@@ -0,0 +1,862 @@
1
+ Metadata-Version: 2.4
2
+ Name: exposr
3
+ Version: 0.5.2
4
+ Summary: Expose local TCP and UDP services to the public internet
5
+ Requires-Python: >=3.8
6
+ Description-Content-Type: text/markdown
7
+ Dynamic: description
8
+ Dynamic: description-content-type
9
+ Dynamic: requires-python
10
+ Dynamic: summary
11
+
12
+ ```text
13
+ _____
14
+ | ____|_ ___ __ ___ ___ _ __
15
+ | _| \ \/ / '_ \ / _ \/ __| '__|
16
+ | |___ > <| |_) | (_) \__ \ |
17
+ |_____/_/\_\ .__/ \___/|___/_|
18
+ |_|
19
+ ```
20
+
21
+ # Exposr
22
+
23
+ Exposr is a reverse TCP and UDP tunneling project that exposes services running
24
+ on a user's local machine to the public internet through a remote relay server.
25
+
26
+ The project is built with Python and uses a public server as the relay. The agent maintains a persistent control connection and creates a dedicated data connection for every incoming public connection.
27
+
28
+ ## Current Version
29
+
30
+ **Exposr v0.5 - Experimental / Proof of Concept**
31
+
32
+ ### Current capabilities
33
+
34
+ - Reverse TCP tunneling
35
+ - Reverse UDP tunneling
36
+ - Localhost service exposure
37
+ - Dynamic public port registration
38
+ - TCP and UDP port availability checking through server registration
39
+ - Persistent agent connection
40
+ - Automatic agent reconnection
41
+ - Multiple simultaneous public connections
42
+ - Dedicated data tunnel per connection
43
+ - UUID-based connection identification
44
+ - Async networking using Python `asyncio`
45
+ - Colored logs for connected, trying, error, and info events
46
+ - Command-line interface
47
+
48
+ Simple TCP tunnel syntax:
49
+
50
+ ```bash
51
+ exposr tcp 3000 25565
52
+ ```
53
+
54
+ Simple UDP tunnel syntax:
55
+
56
+ ```bash
57
+ exposr udp 3000 25565
58
+ ```
59
+
60
+ ---
61
+
62
+ # How It Works
63
+
64
+ Suppose an application is running locally:
65
+
66
+ ```text
67
+ 127.0.0.1:3000
68
+ ```
69
+
70
+ Start Exposr:
71
+
72
+ ```bash
73
+ exposr tcp 3000 25565
74
+ ```
75
+
76
+ The agent creates an outbound connection to the Exposr relay server.
77
+
78
+ UDP tunnels use the same control connection and public-port selection as TCP.
79
+ The public UDP listener forwards each datagram to the local UDP service. UDP
80
+ payloads travel through the existing TCP data channel using length-prefixed
81
+ frames, then are sent back as UDP datagrams.
82
+
83
+ ```text
84
+ Your PC
85
+ 127.0.0.1:3000
86
+ |
87
+ v
88
+ Exposr Agent
89
+ |
90
+ | Persistent control connection
91
+ v
92
+ +--------------------------+
93
+ | Exposr Server |
94
+ | |
95
+ | Control Port: 9000 |
96
+ | Data Port: 9001 |
97
+ | |
98
+ | Public TCP/UDP Ports: |
99
+ | 25565 |
100
+ | 20000-30000 |
101
+ +-------------+------------+
102
+ |
103
+ v
104
+ Internet Users
105
+ ```
106
+
107
+ Example forwarding path:
108
+
109
+ ```text
110
+ Internet User
111
+ |
112
+ v
113
+ SERVER_IP:25565
114
+ |
115
+ v
116
+ Exposr Server
117
+ |
118
+ v
119
+ Exposr Agent
120
+ |
121
+ v
122
+ 127.0.0.1:3000
123
+ |
124
+ v
125
+ Your Application
126
+ ```
127
+
128
+ The application continues running on the user's computer. The relay server only forwards traffic.
129
+
130
+ ---
131
+
132
+ # Project Structure
133
+
134
+ ```text
135
+ Exposr/
136
+ |
137
+ +-- client/
138
+ | +-- __init__.py
139
+ | +-- config.py
140
+ | +-- main.py
141
+ | +-- tcp/
142
+ | | +-- __init__.py
143
+ | | +-- connection.py
144
+ | | +-- tunnel.py
145
+ | +-- udp/
146
+ | +-- __init__.py
147
+ | +-- connection.py
148
+ | +-- tunnel.py
149
+ |
150
+ +-- common/
151
+ | +-- __init__.py
152
+ | +-- logger.py
153
+ | +-- protocol.py
154
+ |
155
+ +-- server/
156
+ | +-- __init__.py
157
+ | +-- control.py
158
+ | +-- data.py
159
+ | +-- ports.py
160
+ | +-- main.py
161
+ | +-- tcp/
162
+ | | +-- __init__.py
163
+ | | +-- ports.py
164
+ | | +-- tunnel.py
165
+ | +-- udp/
166
+ | +-- __init__.py
167
+ | +-- ports.py
168
+ | +-- tunnel.py
169
+ |
170
+ +-- setup.py
171
+ +-- README.MD
172
+ ```
173
+
174
+ TCP- and UDP-specific client and server logic lives in their respective
175
+ transport packages. Shared client and server coordination stays in the
176
+ top-level packages, while shared logging and protocol messages live in
177
+ `common/`.
178
+
179
+ ---
180
+
181
+ # CLI Installation
182
+
183
+ Exposr can be installed as a command-line tool.
184
+
185
+ Clone the repository and navigate into the project:
186
+
187
+ ```bash
188
+ git clone YOUR_REPOSITORY_URL
189
+ cd Exposr
190
+ ```
191
+
192
+ Install Exposr:
193
+
194
+ ```bash
195
+ python -m pip install .
196
+ ```
197
+
198
+ For development, use an editable installation:
199
+
200
+ ```bash
201
+ python -m pip install -e .
202
+ ```
203
+
204
+ The console command is provided by the `client.main:main` entry point as `exposr`. The editable installation means source changes are immediately used without reinstalling the package.
205
+
206
+ ## Configure the Relay Server
207
+
208
+ The server address is blank when Exposr is first installed. Before using
209
+ `tcp` or `udp`, save the public IP address or hostname of the relay VM:
210
+
211
+ ```bash
212
+ exposr config set-server YOUR_SERVER_IP
213
+ ```
214
+
215
+ For example:
216
+
217
+ ```bash
218
+ exposr config set-server 12.345.67.890
219
+ ```
220
+
221
+ This generates a random agent token and saves it in:
222
+
223
+ ```text
224
+ ~/.exposr/agent_token.txt
225
+ ```
226
+
227
+ Copy the contents of that file into the server's
228
+ `~/.exposr/config.json`:
229
+
230
+ ```json
231
+ {
232
+ "server_host": "",
233
+ "agent_token": "PASTE_TOKEN_HERE"
234
+ }
235
+ ```
236
+
237
+ The token is sent with every control registration request. The server closes
238
+ connections whose token does not match its configured token before accepting
239
+ the agent or opening a public tunnel.
240
+
241
+ On the relay server, initialize the token by pasting the generated value:
242
+
243
+ ```bash
244
+ exposr server init-token PASTE_TOKEN_HERE
245
+ ```
246
+
247
+ This writes the token to the server's `~/.exposr/config.json` while preserving
248
+ other configuration values.
249
+
250
+ Start the relay server with:
251
+
252
+ ```bash
253
+ exposr server start
254
+ ```
255
+
256
+ The server must be initialized with `exposr server init-token` before it can
257
+ start accepting authenticated agents.
258
+
259
+ The value is saved in:
260
+
261
+ ```text
262
+ ~/.exposr/config.json
263
+ ```
264
+
265
+ If you run `exposr tcp 3000 25565` before configuring the server, Exposr
266
+ stops and displays:
267
+
268
+ ```text
269
+ [ERROR] Server IP is not configured. Run: exposr config set-server <server-ip>
270
+ ```
271
+
272
+ The `--server-host` option can be used to override the saved address for one
273
+ run:
274
+
275
+ ```bash
276
+ exposr tcp 3000 25565 --server-host YOUR_SERVER_IP
277
+ ```
278
+
279
+ ---
280
+
281
+ # Windows PATH Setup
282
+
283
+ Depending on the Python installation, the Exposr executable may be installed in a Python `Scripts` directory that is not automatically added to `PATH`.
284
+
285
+ If this happens:
286
+
287
+ ```text
288
+ 'exposr' is not recognized as an internal or external command
289
+ ```
290
+
291
+ Find the Python user base directory:
292
+
293
+ ```cmd
294
+ python -m site --user-base
295
+ ```
296
+
297
+ Then add the `Scripts` directory inside that location to the Windows `PATH`. To check where `exposr.exe` exists, run:
298
+
299
+ ```cmd
300
+ where exposr
301
+ ```
302
+
303
+ After adding the correct directory to `PATH`, close existing terminals and open a new terminal. Verify with `where exposr`, then run:
304
+
305
+ ```cmd
306
+ exposr tcp 3000 25565
307
+ ```
308
+
309
+ ---
310
+
311
+ # Using the CLI
312
+
313
+ ## Basic Usage
314
+
315
+ Expose a local TCP service running on port `3000` through public port `25565`:
316
+
317
+ ```bash
318
+ exposr tcp 3000 25565
319
+ ```
320
+
321
+ Exposr requests the specified public port and reports an error if it is unavailable.
322
+ When the public port is omitted, Exposr tries `25565` first and then selects
323
+ random ports from `20000-30000` until it finds one that the server accepts.
324
+
325
+ The same syntax and port-selection behavior apply to UDP:
326
+
327
+ ```bash
328
+ exposr udp 3000
329
+ exposr udp 3000 21342
330
+ ```
331
+
332
+ Optional connection settings can be supplied with:
333
+
334
+ ```text
335
+ --server-host
336
+ --control-port
337
+ --data-port
338
+ --local-host
339
+ ```
340
+
341
+ The saved server address is used when `--server-host` is omitted. The control
342
+ port defaults to `9000`, the data port defaults to `9001`, and the local host
343
+ defaults to `127.0.0.1`.
344
+
345
+ ## TCP Tunnels
346
+
347
+ The TCP command accepts an optional public port:
348
+
349
+ ```bash
350
+ exposr tcp 3000 21342
351
+ ```
352
+
353
+ This forwards:
354
+
355
+ ```text
356
+ 127.0.0.1:3000 -> SERVER_IP:21342
357
+ ```
358
+
359
+ The syntax is:
360
+
361
+ ```text
362
+ exposr tcp <local-port> [public-port]
363
+ ```
364
+
365
+ Examples:
366
+
367
+ ```bash
368
+ exposr tcp 3000 25565
369
+ exposr tcp 8080 28080
370
+ exposr tcp 5000 25000
371
+ exposr tcp 25565 25565
372
+ ```
373
+
374
+ When a public port is supplied, Exposr requests that exact port and reports an
375
+ error if it is unavailable. When omitted, it uses the fallback described above.
376
+
377
+ ## UDP Tunnels
378
+
379
+ UDP exposes a local UDP service through a public UDP port:
380
+
381
+ ```text
382
+ exposr udp <local-port> [public-port]
383
+ ```
384
+
385
+ Examples:
386
+
387
+ ```bash
388
+ exposr udp 3000
389
+ exposr udp 5000 25000
390
+ ```
391
+
392
+ With no public port, Exposr tries `25565`, then random ports from `20000-30000`.
393
+ With a public port, it requests that exact port. Each incoming public datagram
394
+ gets a temporary tunnel session to the local UDP service, and responses are
395
+ returned to the original sender.
396
+
397
+ ---
398
+
399
+ # Port Assignment
400
+
401
+ For either TCP or UDP, Exposr requests the public port supplied on the command line:
402
+
403
+ ```text
404
+ requested public port
405
+ |
406
+ v
407
+ available?
408
+ |
409
+ +-- yes -> register tunnel
410
+ |
411
+ +-- no -> try another random port from 20000-30000
412
+ ```
413
+
414
+ When no public port is supplied, the agent tries `25565` first. The server
415
+ tracks ownership and releases public ports when an agent disconnects.
416
+
417
+ ---
418
+
419
+ # Ports
420
+
421
+ | Port | Purpose |
422
+ |---|---|
423
+ | `9000` | Persistent agent control channel |
424
+ | `9001` | Dedicated TCP data tunnel connections, including UDP payload frames |
425
+ | `25565` | Default preferred public tunnel port |
426
+ | `20000-30000` | Random fallback public tunnel range |
427
+
428
+ The relay host or Azure firewall must allow inbound TCP and UDP traffic for the
429
+ public tunnel ports, and inbound TCP traffic for ports `9000` and `9001`.
430
+
431
+ ## Port 9000 - Control Channel
432
+
433
+ The agent maintains a persistent connection to:
434
+
435
+ ```text
436
+ SERVER_IP:9000
437
+ ```
438
+
439
+ The agent registers a public port:
440
+
441
+ ```text
442
+ REGISTER 25565
443
+ ```
444
+
445
+ For UDP, the registration includes the transport marker:
446
+
447
+ ```text
448
+ REGISTER 25565 <agent-token> UDP
449
+ ```
450
+
451
+ When an internet user connects to the public port, the server sends the agent:
452
+
453
+ ```text
454
+ CONNECT <connection-id>
455
+ ```
456
+
457
+ Example:
458
+
459
+ ```text
460
+ CONNECT 8bab2f9a-b0e2-4db2-8fed-9a8dda8e3aed
461
+ ```
462
+
463
+ ## Port 9001 - Data Channel
464
+
465
+ For each incoming public connection:
466
+
467
+ 1. The server generates a UUID.
468
+ 2. The server tells the correct agent to handle it.
469
+ 3. The agent connects to the local application.
470
+ 4. The agent opens a new connection to port `9001`.
471
+ 5. The agent identifies that connection with:
472
+
473
+ ```text
474
+ DATA <connection-id>
475
+ ```
476
+
477
+ 6. The server matches the data connection with the waiting public client.
478
+ 7. Traffic is forwarded in both directions.
479
+
480
+ Each public client receives a separate data connection.
481
+
482
+ For UDP, port `9001` carries length-prefixed datagram frames over a temporary
483
+ TCP data connection. The public and local service endpoints remain UDP sockets.
484
+
485
+ ---
486
+
487
+ # Requirements
488
+
489
+ ## Server
490
+
491
+ - Python 3.10+
492
+ - Linux server, VPS, Azure VM, or another machine with a reachable public IP
493
+ - Open inbound TCP ports `9000` and `9001`
494
+ - Open inbound UDP port `25565` and the UDP range `20000-30000`
495
+
496
+ ## Client
497
+
498
+ - Python 3.10+
499
+ - Internet connection
500
+ - A local TCP or UDP service running on the desired port
501
+
502
+ ---
503
+
504
+ # Server Setup
505
+
506
+ On the relay machine, clone the project and enter its directory:
507
+
508
+ ```bash
509
+ git clone YOUR_REPOSITORY_URL
510
+ cd Exposr
511
+ ```
512
+
513
+ Install Exposr:
514
+
515
+ ```bash
516
+ python3 -m pip install .
517
+ ```
518
+
519
+ Initialize the server with the agent token generated by the client setup:
520
+
521
+ ```bash
522
+ exposr server init-token PASTE_TOKEN_HERE
523
+ ```
524
+
525
+ Before starting the relay, allow inbound TCP traffic on ports `9000` and
526
+ `9001`, and allow inbound TCP and UDP traffic on public tunnel ports `25565`
527
+ and `20000-30000`. The public port protocol must match the tunnel command:
528
+
529
+ ```text
530
+ exposr tcp 3000 # public TCP port
531
+ exposr udp 3000 # public UDP port
532
+ ```
533
+
534
+ Start the relay server with:
535
+
536
+ ```bash
537
+ exposr server start
538
+ ```
539
+
540
+ The server listens on TCP control port `9000` and TCP data port `9001`. It
541
+ creates a TCP or UDP public listener when an authenticated agent registers a
542
+ tunnel. Keep this process running while clients use the relay.
543
+
544
+ ---
545
+
546
+ # Example: FastAPI
547
+
548
+ Suppose FastAPI runs locally on `127.0.0.1:3000`:
549
+
550
+ ```bash
551
+ uvicorn main:app --host 127.0.0.1 --port 3000
552
+ ```
553
+
554
+ Start Exposr:
555
+
556
+ ```bash
557
+ exposr tcp 3000 25565
558
+ ```
559
+
560
+ If Exposr assigns `25565`, visiting `http://SERVER_IP:25565` forwards traffic to `http://127.0.0.1:3000`. Swagger documentation is available through `http://SERVER_IP:25565/docs` when that public port is assigned.
561
+
562
+ For a local UDP service listening on port `3000`, run:
563
+
564
+ ```bash
565
+ exposr udp 3000
566
+ ```
567
+
568
+ Send UDP datagrams to `SERVER_IP:25565`. If `25565` is unavailable, the agent
569
+ selects and registers an available port from `20000-30000`.
570
+
571
+ ---
572
+
573
+ # Multiple Agents
574
+
575
+ The server supports multiple agents. Each agent can own a different public port, while the server tracks the owner of each tunnel:
576
+
577
+ ```text
578
+ Agent A: 127.0.0.1:3000 -> SERVER_IP:25565
579
+ Agent B: 127.0.0.1:8080 -> SERVER_IP:28061
580
+ Agent C: 127.0.0.1:5000 -> SERVER_IP:29040
581
+ ```
582
+
583
+ # Multiple Simultaneous Connections
584
+
585
+ Multiple users can connect to the same public port simultaneously. Every connection receives a unique UUID and a dedicated data connection:
586
+
587
+ ```text
588
+ Client A --+
589
+ |
590
+ Client B --+----> Exposr Server
591
+ | |
592
+ Client C --+ +-- Tunnel A --> Local Service
593
+ +-- Tunnel B --> Local Service
594
+ +-- Tunnel C --> Local Service
595
+ ```
596
+
597
+ ---
598
+
599
+ # Logging
600
+
601
+ Exposr uses colored status logs.
602
+
603
+ ## Green - `[CONNECTED]`
604
+
605
+ Used for successful connections and active tunnels.
606
+
607
+ ## Yellow - `[TRYING]`
608
+
609
+ Used while connecting, registering ports, and creating tunnels.
610
+
611
+ ## Red - `[ERROR]`
612
+
613
+ Used for failures, timeouts, disconnections, and cleanup.
614
+
615
+ ## Blue - `[INFO]`
616
+
617
+ Used for informational messages such as clean shutdown.
618
+
619
+ ---
620
+
621
+ # Azure / Firewall Configuration
622
+
623
+ The relay server firewall or cloud security rules must allow inbound traffic for:
624
+
625
+ | Port / Range | Protocol | Purpose |
626
+ |---|---|---|
627
+ | `22` | TCP | SSH, if required for administration |
628
+ | `9000` | TCP | Exposr control channel |
629
+ | `9001` | TCP | Exposr data channel |
630
+ | `25565` | TCP/UDP | Default public tunnel port |
631
+ | `20000-30000` | TCP/UDP | Random fallback public tunnel range |
632
+
633
+ The requested public port must be allowed for the matching protocol through the
634
+ cloud firewall or Network Security Group. TCP tunnels need TCP access; UDP
635
+ tunnels need UDP access. Ports `9000` and `9001` always use TCP.
636
+
637
+ ---
638
+
639
+ # Current Architecture
640
+
641
+ ```text
642
+ +---------------------+
643
+ | Internet User |
644
+ +----------+----------+
645
+ |
646
+ v
647
+ SERVER_IP:PUBLIC_PORT
648
+ |
649
+ v
650
+ +---------------------+
651
+ | Exposr Server |
652
+ | |
653
+ | Control -> 9000 |
654
+ | Data -> 9001 |
655
+ | |
656
+ | Public TCP/UDP |
657
+ | 25565 |
658
+ | 20000-30000 |
659
+ +----------+----------+
660
+ |
661
+ | Persistent outbound
662
+ | control connection
663
+ v
664
+ +---------------------+
665
+ | Exposr Agent |
666
+ +----------+----------+
667
+ |
668
+ v
669
+ +---------------------+
670
+ | Local Service |
671
+ | 127.0.0.1:LOCAL_PORT|
672
+ +---------------------+
673
+ ```
674
+
675
+ ---
676
+
677
+ ---
678
+
679
+ # Benchmarks
680
+
681
+ Exposr v0.4 was benchmarked against a direct (non-tunneled) baseline to measure protocol overhead.
682
+
683
+ ## Test Environment
684
+
685
+ **Relay server:**
686
+ - Azure Standard_B1s (1 vCPU, 1 GiB RAM, burstable)
687
+ - Region: Central India
688
+ - OS: Ubuntu 24.04
689
+
690
+ **Client:** Windows, local network connection to Azure
691
+
692
+ **Method:** 100 sequential HTTP GET requests per run, measured with an async
693
+ benchmark harness (`aiohttp`). Direct requests hit the local service on
694
+ `127.0.0.1`; tunneled requests hit the same service through the public
695
+ Exposr port.
696
+
697
+ ## Results
698
+
699
+ | Metric | Direct | Tunneled | Overhead |
700
+ |---|---|---|---|
701
+ | Mean latency | 80.80 ms | 547.77 ms | +466.97 ms |
702
+ | Median latency | 78.59 ms | 541.00 ms | +462.41 ms |
703
+ | p95 latency | 110.20 ms | 587.42 ms | +477.22 ms |
704
+ | p99 latency | 124.50 ms | 623.29 ms | +498.79 ms |
705
+ | Throughput | 12.4 req/s | 1.8 req/s | -85.5% |
706
+
707
+ Raw TCP connect time to the relay server (`curl -w "%{time_connect}"`)
708
+ measured **113 ms**, isolating pure network RTT from protocol-level cost.
709
+
710
+ ## Overhead Breakdown
711
+
712
+ ```text
713
+ Total tunneled latency: 547.77 ms
714
+ Network RTT (TCP connect): -113.00 ms
715
+ --------------------------------------
716
+ Exposr protocol overhead: ~435 ms
717
+ ```
718
+
719
+ The majority of tunneled latency is not raw network distance but overhead
720
+ introduced by Exposr's connection lifecycle:
721
+
722
+ - A fresh TCP handshake for the **data channel** (port `9001`) on every
723
+ request, since each public connection gets a dedicated data tunnel
724
+ rather than a reused/pooled connection
725
+ - A control-channel round trip (`CONNECT <uuid>` → agent dial-back with
726
+ `DATA <uuid>`) that must complete before any payload is forwarded
727
+ - No connection keep-alive or pooling on the tunnel path, so this cost
728
+ repeats on every single request instead of being amortized
729
+
730
+ ## Known Confounds
731
+
732
+ - The relay server runs on the cheapest available Azure tier
733
+ (Standard_B1s), which is CPU-credit throttled under sustained load.
734
+ Some of the measured overhead is plausibly hardware-imposed rather than
735
+ protocol-imposed.
736
+ - Direct-baseline latency (80 ms on `127.0.0.1`) is higher than a typical
737
+ loopback benchmark, likely due to the local test server used
738
+ (`python -m http.server` is single-threaded/blocking). A faster local
739
+ server would tighten the baseline and slightly increase the reported
740
+ overhead percentage.
741
+
742
+ ## Reproducing
743
+
744
+ ```bash
745
+ pip install aiohttp
746
+ python exposr_benchmark.py \
747
+ --direct-url http://127.0.0.1:3000/ \
748
+ --tunnel-url http://YOUR_SERVER_IP:25565/ \
749
+ --requests 100
750
+ ```
751
+
752
+ Concurrency sweep:
753
+
754
+ ```bash
755
+ python exposr_benchmark.py \
756
+ --direct-url http://127.0.0.1:3000/ \
757
+ --tunnel-url http://YOUR_SERVER_IP:25565/ \
758
+ --concurrency 1 10 50 100 \
759
+ --requests 200
760
+ ```
761
+
762
+ This overhead is the primary target for the connection-reuse and
763
+ persistent-tunnel work listed under **Planned Features**.
764
+
765
+ # Current Limitations
766
+
767
+ Exposr is currently an experimental proof of concept.
768
+
769
+ Known limitations:
770
+
771
+ - TCP and UDP forwarding use separate public sockets
772
+ - No encryption or TLS
773
+ - Data connections are not separately authenticated
774
+ - No domain or subdomain routing
775
+ - No persistent tunnel configuration
776
+ - No user accounts or dashboard
777
+ - No rate limiting or abuse protection
778
+ - Public port ranges must be explicitly allowed by the server firewall
779
+ - Random port allocation does not bypass firewall or cloud security rules
780
+ - UDP forwarding uses temporary TCP data connections for payload transport
781
+
782
+ ---
783
+
784
+ # Security Warning
785
+
786
+ The current version is not production-ready. The control port uses the
787
+ configured agent token, but the data port does not use separate
788
+ authentication or encryption. Do not expose the control and data ports
789
+ publicly in a production deployment without appropriate security controls.
790
+
791
+ ---
792
+
793
+ # Planned Features
794
+
795
+ Possible future improvements include:
796
+
797
+ - Server-assigned ports
798
+ - Agent heartbeat and stale-agent detection
799
+ - Improved tunnel registration
800
+ - Persistent server operation using `systemd`
801
+ - Agent authentication tokens
802
+ - TLS encryption
803
+ - Domain support
804
+ - CLI status and tunnel management commands
805
+
806
+ These are not part of the current protocol or implementation.
807
+
808
+ ---
809
+
810
+ # Development Status
811
+
812
+ ```text
813
+ Exposr v0.4
814
+ Experimental / Proof of Concept
815
+ ```
816
+
817
+ The current version demonstrates the core functionality of Exposr: exposing
818
+ local TCP and UDP services through a publicly accessible relay server with
819
+ dynamic port registration, automatic fallback allocation, dedicated TCP data
820
+ tunnels, UDP datagram forwarding, and a command-line interface.
821
+
822
+ ---
823
+
824
+ # CLI Quick Reference
825
+
826
+ ```bash
827
+ # Install Exposr
828
+ python -m pip install .
829
+
830
+ # Development installation
831
+ python -m pip install -e .
832
+
833
+ # Configure the relay server once
834
+ exposr config set-server YOUR_SERVER_IP
835
+
836
+ # Expose a local TCP service using the default public port
837
+ exposr tcp 3000 25565
838
+
839
+ # Expose a local service using a specific public port
840
+ exposr tcp 3000 21342
841
+
842
+ # Expose another local service
843
+ exposr tcp 8080 28080
844
+
845
+ # Expose a Minecraft Java server on its default local port
846
+ exposr tcp 25565 25565
847
+
848
+ # Expose a local UDP service using the default public port
849
+ exposr udp 3000
850
+
851
+ # Expose a local UDP service using a specific public port
852
+ exposr udp 3000 21342
853
+ ```
854
+
855
+ The general TCP syntax is:
856
+
857
+ ```text
858
+ exposr tcp <local-port> [public-port]
859
+ ```
860
+
861
+ UDP uses the parallel syntax `exposr udp <local-port> [public-port]` and follows
862
+ the same `25565` then `20000-30000` fallback behavior as TCP.