linksocks 3.0.12__tar.gz → 3.0.13__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.
Potentially problematic release.
This version of linksocks might be problematic. Click here for more details.
- linksocks-3.0.13/PKG-INFO +493 -0
- linksocks-3.0.13/README.md +430 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks/__init__.py +1 -1
- linksocks-3.0.13/linksocks.egg-info/PKG-INFO +493 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks.egg-info/SOURCES.txt +1 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks_go/version.go +1 -1
- {linksocks-3.0.12 → linksocks-3.0.13}/setup.py +1 -1
- linksocks-3.0.12/PKG-INFO +0 -64
- linksocks-3.0.12/linksocks.egg-info/PKG-INFO +0 -64
- {linksocks-3.0.12 → linksocks-3.0.13}/MANIFEST.in +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/go.mod +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/go.sum +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks/_base.py +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks/_cli.py +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks/_client.py +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks/_logging_config.py +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks/_server.py +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks/_utils.py +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks.egg-info/dependency_links.txt +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks.egg-info/entry_points.txt +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks.egg-info/not-zip-safe +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks.egg-info/requires.txt +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks.egg-info/top_level.txt +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks_go/_python.go +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks_go/api.go +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks_go/batchlog.go +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks_go/cli.go +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks_go/client.go +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks_go/conn.go +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks_go/doc.go +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks_go/forwarder.go +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks_go/message.go +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks_go/portpool.go +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks_go/relay.go +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks_go/server.go +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/linksocks_go/socket.go +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/setup.cfg +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/tests/test_crash.py +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/tests/test_lib.py +0 -0
- {linksocks-3.0.12 → linksocks-3.0.13}/tests/test_wrapper.py +0 -0
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: linksocks
|
|
3
|
+
Version: 3.0.13
|
|
4
|
+
Summary: Python bindings for LinkSocks - SOCKS proxy over WebSocket
|
|
5
|
+
Home-page: https://github.com/linksocks/linksocks
|
|
6
|
+
Author: jackzzs
|
|
7
|
+
Author-email: jackzzs@outlook.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Bug Reports, https://github.com/linksocks/linksocks/issues
|
|
10
|
+
Project-URL: Source, https://github.com/linksocks/linksocks
|
|
11
|
+
Project-URL: Documentation, https://github.com/linksocks/linksocks#readme
|
|
12
|
+
Project-URL: Changelog, https://github.com/linksocks/linksocks/releases
|
|
13
|
+
Keywords: socks proxy websocket network tunneling firewall bypass load-balancing go bindings
|
|
14
|
+
Platform: any
|
|
15
|
+
Classifier: Development Status :: 4 - Beta
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Intended Audience :: System Administrators
|
|
18
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
19
|
+
Classifier: Operating System :: MacOS
|
|
20
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
27
|
+
Classifier: Programming Language :: Go
|
|
28
|
+
Classifier: Topic :: Internet :: Proxy Servers
|
|
29
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
30
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
31
|
+
Classifier: Topic :: System :: Networking
|
|
32
|
+
Requires-Python: >=3.9
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
Requires-Dist: setuptools>=40.0
|
|
35
|
+
Requires-Dist: click>=8.0
|
|
36
|
+
Requires-Dist: loguru
|
|
37
|
+
Requires-Dist: rich
|
|
38
|
+
Provides-Extra: dev
|
|
39
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
40
|
+
Requires-Dist: pytest-cov>=2.10; extra == "dev"
|
|
41
|
+
Requires-Dist: pytest-mock>=3.0; extra == "dev"
|
|
42
|
+
Requires-Dist: pytest-xdist; extra == "dev"
|
|
43
|
+
Requires-Dist: black>=21.0; extra == "dev"
|
|
44
|
+
Requires-Dist: flake8>=3.8; extra == "dev"
|
|
45
|
+
Requires-Dist: mypy>=0.800; extra == "dev"
|
|
46
|
+
Requires-Dist: httpx[socks]; extra == "dev"
|
|
47
|
+
Requires-Dist: requests; extra == "dev"
|
|
48
|
+
Requires-Dist: pysocks; extra == "dev"
|
|
49
|
+
Dynamic: author
|
|
50
|
+
Dynamic: author-email
|
|
51
|
+
Dynamic: classifier
|
|
52
|
+
Dynamic: description
|
|
53
|
+
Dynamic: description-content-type
|
|
54
|
+
Dynamic: home-page
|
|
55
|
+
Dynamic: keywords
|
|
56
|
+
Dynamic: license
|
|
57
|
+
Dynamic: platform
|
|
58
|
+
Dynamic: project-url
|
|
59
|
+
Dynamic: provides-extra
|
|
60
|
+
Dynamic: requires-dist
|
|
61
|
+
Dynamic: requires-python
|
|
62
|
+
Dynamic: summary
|
|
63
|
+
|
|
64
|
+
# LinkSocks Python Bindings
|
|
65
|
+
|
|
66
|
+
[](https://badge.fury.io/py/linksocks)
|
|
67
|
+
[](https://pypi.org/project/linksocks/)
|
|
68
|
+
[](https://opensource.org/licenses/MIT)
|
|
69
|
+
|
|
70
|
+
Python bindings for LinkSocks - a SOCKS5 over WebSocket proxy tool.
|
|
71
|
+
|
|
72
|
+
## Overview
|
|
73
|
+
|
|
74
|
+
LinkSocks is a SOCKS proxy implementation over WebSocket protocol that allows you to securely expose SOCKS proxy services under Web Application Firewall (WAF) protection. This package provides Python bindings for the Go implementation.
|
|
75
|
+
|
|
76
|
+
### Key Features
|
|
77
|
+
|
|
78
|
+
- 🔄 **Forward & Reverse Proxy**: Support both forward and reverse SOCKS5 proxy modes
|
|
79
|
+
- 🌐 **WebSocket Transport**: Works under WAF protection using standard WebSocket connections
|
|
80
|
+
- ⚖️ **Load Balancing**: Round-robin load balancing for reverse proxy with multiple clients
|
|
81
|
+
- 🔐 **Authentication**: SOCKS5 proxy authentication and secure token-based WebSocket authentication
|
|
82
|
+
- 🌍 **Protocol Support**: Full IPv6 over SOCKS5 and UDP over SOCKS5 support
|
|
83
|
+
- 🐍 **Pythonic API**: Both synchronous and asynchronous APIs with context manager support
|
|
84
|
+
|
|
85
|
+
## Installation
|
|
86
|
+
|
|
87
|
+
### Using pip (Recommended)
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
pip install linksocks
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Development Installation
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
git clone https://github.com/linksocks/linksocks.git
|
|
97
|
+
cd linksocks/_bindings/python
|
|
98
|
+
pip install -e .
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Requirements
|
|
102
|
+
|
|
103
|
+
- Python 3.8 or later
|
|
104
|
+
- Go 1.19 or later (for building from source)
|
|
105
|
+
|
|
106
|
+
## Quick Start
|
|
107
|
+
|
|
108
|
+
### Forward Proxy Example
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
import asyncio
|
|
112
|
+
from linksocks import Server, Client
|
|
113
|
+
|
|
114
|
+
async def main():
|
|
115
|
+
# Create server and client with async context managers
|
|
116
|
+
async with Server(ws_port=8765) as server:
|
|
117
|
+
# Add forward token asynchronously
|
|
118
|
+
token = await server.async_add_forward_token()
|
|
119
|
+
|
|
120
|
+
async with Client(token, ws_url="ws://localhost:8765", socks_port=9870, no_env_proxy=True) as client:
|
|
121
|
+
print("✅ Forward proxy ready!")
|
|
122
|
+
print("🌐 SOCKS5 proxy: 127.0.0.1:9870")
|
|
123
|
+
print("🔧 Test: curl --socks5 127.0.0.1:9870 http://httpbin.org/ip")
|
|
124
|
+
|
|
125
|
+
# Keep running
|
|
126
|
+
await asyncio.sleep(3600)
|
|
127
|
+
|
|
128
|
+
if __name__ == "__main__":
|
|
129
|
+
asyncio.run(main())
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Reverse Proxy Example
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
import asyncio
|
|
136
|
+
from linksocks import Server, Client
|
|
137
|
+
|
|
138
|
+
async def main():
|
|
139
|
+
# Create server and client with async context managers
|
|
140
|
+
async with Server(ws_port=8765) as server:
|
|
141
|
+
# Add reverse token (port is auto-allocated)
|
|
142
|
+
result = server.add_reverse_token()
|
|
143
|
+
print(f"🔑 Reverse token: {result.token}")
|
|
144
|
+
print(f"🌐 SOCKS5 proxy will be available on: 127.0.0.1:{result.port}")
|
|
145
|
+
|
|
146
|
+
# Create client in reverse mode
|
|
147
|
+
async with Client(result.token, ws_url="ws://localhost:8765", reverse=True, no_env_proxy=True) as client:
|
|
148
|
+
print("✅ Reverse proxy ready!")
|
|
149
|
+
print(f"🔧 Test: curl --socks5 127.0.0.1:{result.port} http://httpbin.org/ip")
|
|
150
|
+
|
|
151
|
+
# Keep running
|
|
152
|
+
await asyncio.sleep(3600)
|
|
153
|
+
|
|
154
|
+
if __name__ == "__main__":
|
|
155
|
+
asyncio.run(main())
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## API Reference
|
|
159
|
+
|
|
160
|
+
### Server Class
|
|
161
|
+
|
|
162
|
+
The `Server` class manages WebSocket connections and provides SOCKS5 proxy functionality.
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
from linksocks import Server
|
|
166
|
+
|
|
167
|
+
# Create server with options
|
|
168
|
+
server = Server(
|
|
169
|
+
ws_host="0.0.0.0", # WebSocket listen address
|
|
170
|
+
ws_port=8765, # WebSocket listen port
|
|
171
|
+
socks_host="127.0.0.1", # SOCKS5 listen address (reverse mode)
|
|
172
|
+
buffer_size=32768, # Buffer size for data transfer
|
|
173
|
+
api_key="your_api_key", # Enable HTTP API
|
|
174
|
+
channel_timeout=30.0, # WebSocket channel timeout (seconds)
|
|
175
|
+
connect_timeout=10.0, # Connection timeout (seconds)
|
|
176
|
+
fast_open=False, # Enable fast open optimization
|
|
177
|
+
upstream_proxy="socks5://proxy:1080", # Upstream proxy
|
|
178
|
+
upstream_username="user", # Upstream proxy username
|
|
179
|
+
upstream_password="pass" # Upstream proxy password
|
|
180
|
+
)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
#### Token Management
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
# Add forward proxy token (synchronous)
|
|
187
|
+
token = server.add_forward_token("custom_token") # or auto-generate with None
|
|
188
|
+
|
|
189
|
+
# Add forward proxy token (asynchronous - recommended)
|
|
190
|
+
token = await server.async_add_forward_token("custom_token")
|
|
191
|
+
|
|
192
|
+
# Add reverse proxy token
|
|
193
|
+
result = server.add_reverse_token(
|
|
194
|
+
token="custom_token", # optional, auto-generated if None
|
|
195
|
+
port=9870, # optional, auto-allocated if None
|
|
196
|
+
username="socks_user", # optional, SOCKS5 auth username
|
|
197
|
+
password="socks_pass", # optional, SOCKS5 auth password
|
|
198
|
+
allow_manage_connector=True # optional, allow client connector management
|
|
199
|
+
)
|
|
200
|
+
print(f"Token: {result.token}, Port: {result.port}")
|
|
201
|
+
|
|
202
|
+
# Add connector token
|
|
203
|
+
connector_token = server.add_connector_token("connector_token", "reverse_token")
|
|
204
|
+
|
|
205
|
+
# Remove any token
|
|
206
|
+
success = server.remove_token("token_to_remove")
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
#### Running the Server
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
# Asynchronous (recommended) - automatically waits for ready
|
|
213
|
+
async with server:
|
|
214
|
+
print("Server is ready!") # No need for async_wait_ready()
|
|
215
|
+
# Server runs while in context
|
|
216
|
+
|
|
217
|
+
# Synchronous - requires manual wait
|
|
218
|
+
server.wait_ready() # Blocks until ready
|
|
219
|
+
# Server runs in background
|
|
220
|
+
server.close() # Clean shutdown
|
|
221
|
+
|
|
222
|
+
# Manual wait with timeout (only needed for synchronous usage)
|
|
223
|
+
server.wait_ready(timeout=30.0) # 30 second timeout
|
|
224
|
+
await server.async_wait_ready(timeout="30s") # Go duration string (rarely needed)
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Client Class
|
|
228
|
+
|
|
229
|
+
The `Client` class connects to WebSocket servers and provides SOCKS5 functionality.
|
|
230
|
+
|
|
231
|
+
```python
|
|
232
|
+
from linksocks import Client
|
|
233
|
+
|
|
234
|
+
# Create client with options
|
|
235
|
+
client = Client(
|
|
236
|
+
token="your_token", # Authentication token (required)
|
|
237
|
+
ws_url="ws://localhost:8765", # WebSocket server URL
|
|
238
|
+
reverse=False, # Enable reverse proxy mode
|
|
239
|
+
socks_host="127.0.0.1", # SOCKS5 listen address (forward mode)
|
|
240
|
+
socks_port=9870, # SOCKS5 listen port (forward mode)
|
|
241
|
+
socks_username="user", # SOCKS5 auth username
|
|
242
|
+
socks_password="pass", # SOCKS5 auth password
|
|
243
|
+
socks_wait_server=True, # Wait for server before starting SOCKS5
|
|
244
|
+
reconnect=True, # Auto-reconnect on disconnect
|
|
245
|
+
reconnect_delay=5.0, # Reconnect delay (seconds)
|
|
246
|
+
buffer_size=32768, # Buffer size for data transfer
|
|
247
|
+
channel_timeout=30.0, # WebSocket channel timeout
|
|
248
|
+
connect_timeout=10.0, # Connection timeout
|
|
249
|
+
threads=4, # Number of processing threads
|
|
250
|
+
fast_open=False, # Enable fast open optimization
|
|
251
|
+
upstream_proxy="socks5://proxy:1080", # Upstream proxy
|
|
252
|
+
upstream_username="proxy_user", # Upstream proxy username
|
|
253
|
+
upstream_password="proxy_pass", # Upstream proxy password
|
|
254
|
+
no_env_proxy=False # Ignore proxy environment variables
|
|
255
|
+
)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### Running the Client
|
|
259
|
+
|
|
260
|
+
```python
|
|
261
|
+
# Asynchronous (recommended) - automatically waits for ready
|
|
262
|
+
async with client:
|
|
263
|
+
print(f"Client ready! SOCKS5 port: {client.socks_port}")
|
|
264
|
+
print(f"Connected: {client.is_connected}")
|
|
265
|
+
# Client runs while in context
|
|
266
|
+
|
|
267
|
+
# Synchronous - requires manual wait
|
|
268
|
+
client.wait_ready()
|
|
269
|
+
print(f"Connected: {client.is_connected}")
|
|
270
|
+
client.close() # Clean shutdown
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
#### Connector Management (Reverse Mode)
|
|
274
|
+
|
|
275
|
+
```python
|
|
276
|
+
# Add connector token (reverse mode only)
|
|
277
|
+
connector_token = client.add_connector("my_connector") # or auto-generate
|
|
278
|
+
connector_token = await client.async_add_connector(None) # async version
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Logging
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
import logging
|
|
285
|
+
from linksocks import set_log_level
|
|
286
|
+
|
|
287
|
+
# Set global log level
|
|
288
|
+
set_log_level(logging.DEBUG)
|
|
289
|
+
set_log_level("INFO") # String format
|
|
290
|
+
|
|
291
|
+
# Use custom logger
|
|
292
|
+
logger = logging.getLogger("my_app")
|
|
293
|
+
logger.setLevel(logging.DEBUG)
|
|
294
|
+
handler = logging.StreamHandler()
|
|
295
|
+
handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
|
|
296
|
+
logger.addHandler(handler)
|
|
297
|
+
|
|
298
|
+
server = Server(logger=logger)
|
|
299
|
+
client = Client("token", logger=logger)
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## Advanced Examples
|
|
303
|
+
|
|
304
|
+
### Agent Proxy with Connector Management
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
import asyncio
|
|
308
|
+
from linksocks import Server, Client
|
|
309
|
+
|
|
310
|
+
async def agent_proxy():
|
|
311
|
+
# Server with connector autonomy enabled
|
|
312
|
+
async with Server(ws_port=8765) as server:
|
|
313
|
+
result = server.add_reverse_token(allow_manage_connector=True)
|
|
314
|
+
print(f"🔑 Provider token: {result.token}")
|
|
315
|
+
print(f"🌐 SOCKS5 proxy will be available on: 127.0.0.1:{result.port}")
|
|
316
|
+
|
|
317
|
+
# Provider client (provides network access)
|
|
318
|
+
async with Client(result.token, ws_url="ws://localhost:8765", reverse=True, no_env_proxy=True) as provider:
|
|
319
|
+
print("✅ Agent proxy server and provider ready!")
|
|
320
|
+
|
|
321
|
+
# Provider can manage its own connectors
|
|
322
|
+
connector_token = await provider.async_add_connector("my_connector")
|
|
323
|
+
print(f"🔑 Connector token: {connector_token}")
|
|
324
|
+
|
|
325
|
+
# Now external connectors can use this token
|
|
326
|
+
print(f"🔧 Start connector: linksocks connector -t {connector_token} -u ws://localhost:8765 -p 1180")
|
|
327
|
+
|
|
328
|
+
await asyncio.sleep(3600)
|
|
329
|
+
|
|
330
|
+
asyncio.run(agent_proxy())
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Error Handling and Monitoring
|
|
334
|
+
|
|
335
|
+
```python
|
|
336
|
+
import asyncio
|
|
337
|
+
import logging
|
|
338
|
+
from linksocks import Client
|
|
339
|
+
|
|
340
|
+
async def robust_client():
|
|
341
|
+
logger = logging.getLogger("robust_client")
|
|
342
|
+
|
|
343
|
+
client = Client(
|
|
344
|
+
"your_token",
|
|
345
|
+
ws_url="ws://server:8765",
|
|
346
|
+
reconnect=True,
|
|
347
|
+
reconnect_delay=5.0,
|
|
348
|
+
no_env_proxy=True,
|
|
349
|
+
logger=logger
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
try:
|
|
353
|
+
async with client:
|
|
354
|
+
logger.info("✅ Client connected successfully")
|
|
355
|
+
|
|
356
|
+
# Monitor connection status
|
|
357
|
+
while True:
|
|
358
|
+
if not client.is_connected:
|
|
359
|
+
logger.warning("⚠️ Connection lost, reconnecting...")
|
|
360
|
+
|
|
361
|
+
await asyncio.sleep(5)
|
|
362
|
+
|
|
363
|
+
except asyncio.TimeoutError:
|
|
364
|
+
logger.error("❌ Connection timeout after 30 seconds")
|
|
365
|
+
except Exception as e:
|
|
366
|
+
logger.error(f"❌ Client error: {e}")
|
|
367
|
+
finally:
|
|
368
|
+
logger.info("🔄 Client shutting down")
|
|
369
|
+
|
|
370
|
+
asyncio.run(robust_client())
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### HTTP API Integration
|
|
374
|
+
|
|
375
|
+
```python
|
|
376
|
+
import asyncio
|
|
377
|
+
import aiohttp
|
|
378
|
+
from linksocks import Server
|
|
379
|
+
|
|
380
|
+
async def api_server_example():
|
|
381
|
+
# Start server with API enabled
|
|
382
|
+
server = Server(ws_port=8765, api_key="secret_api_key")
|
|
383
|
+
|
|
384
|
+
async with server:
|
|
385
|
+
print("✅ Server with API ready!")
|
|
386
|
+
|
|
387
|
+
# Use HTTP API to manage tokens
|
|
388
|
+
async with aiohttp.ClientSession() as session:
|
|
389
|
+
headers = {"X-API-Key": "secret_api_key"}
|
|
390
|
+
|
|
391
|
+
# Add forward token via API
|
|
392
|
+
async with session.post(
|
|
393
|
+
"http://localhost:8765/api/token",
|
|
394
|
+
headers=headers,
|
|
395
|
+
json={"type": "forward", "token": "api_token"}
|
|
396
|
+
) as resp:
|
|
397
|
+
result = await resp.json()
|
|
398
|
+
print(f"📝 Added token via API: {result}")
|
|
399
|
+
|
|
400
|
+
# Get server status
|
|
401
|
+
async with session.get(
|
|
402
|
+
"http://localhost:8765/api/status",
|
|
403
|
+
headers=headers
|
|
404
|
+
) as resp:
|
|
405
|
+
status = await resp.json()
|
|
406
|
+
print(f"📊 Server status: {status}")
|
|
407
|
+
|
|
408
|
+
await asyncio.sleep(3600)
|
|
409
|
+
|
|
410
|
+
asyncio.run(api_server_example())
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## Type Hints
|
|
414
|
+
|
|
415
|
+
The package includes comprehensive type hints for better IDE support:
|
|
416
|
+
|
|
417
|
+
```python
|
|
418
|
+
from typing import Optional
|
|
419
|
+
from linksocks import Server, Client, ReverseTokenResult
|
|
420
|
+
|
|
421
|
+
def create_proxy_pair(token: str, port: Optional[int] = None) -> tuple[Server, Client]:
|
|
422
|
+
server = Server(ws_port=8765)
|
|
423
|
+
server.add_forward_token(token)
|
|
424
|
+
|
|
425
|
+
client = Client(token, ws_url="ws://localhost:8765", socks_port=port or 9870, no_env_proxy=True)
|
|
426
|
+
return server, client
|
|
427
|
+
|
|
428
|
+
# ReverseTokenResult is a dataclass
|
|
429
|
+
server = Server(ws_port=8765)
|
|
430
|
+
result: ReverseTokenResult = server.add_reverse_token()
|
|
431
|
+
print(f"Token: {result.token}, Port: {result.port}")
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
## Comparison with CLI Tool
|
|
435
|
+
|
|
436
|
+
| Feature | Python Bindings | Go CLI Tool |
|
|
437
|
+
|---------|-----------------|-------------|
|
|
438
|
+
| **Integration** | Library for Python apps | Standalone binary |
|
|
439
|
+
| **API Style** | Object-oriented, async/sync | Command-line flags |
|
|
440
|
+
| **Use Cases** | Embedded in applications | Quick setup, scripting |
|
|
441
|
+
| **Performance** | Same (uses Go backend) | Same |
|
|
442
|
+
| **Features** | Full feature parity | Full feature parity |
|
|
443
|
+
|
|
444
|
+
## Troubleshooting
|
|
445
|
+
|
|
446
|
+
### Common Issues
|
|
447
|
+
|
|
448
|
+
1. **Import Error**: Make sure Go 1.19+ is installed when building from source
|
|
449
|
+
2. **Connection Refused**: Check that server is running and ports are correct
|
|
450
|
+
3. **Authentication Failed**: Verify tokens match between server and client
|
|
451
|
+
4. **Port Already in Use**: Choose different ports or check for existing processes
|
|
452
|
+
|
|
453
|
+
### Debug Logging
|
|
454
|
+
|
|
455
|
+
```python
|
|
456
|
+
import logging
|
|
457
|
+
from linksocks import set_log_level
|
|
458
|
+
|
|
459
|
+
# Enable debug logging
|
|
460
|
+
set_log_level(logging.DEBUG)
|
|
461
|
+
|
|
462
|
+
# Or use environment variable
|
|
463
|
+
import os
|
|
464
|
+
os.environ["LINKSOCKS_LOG_LEVEL"] = "DEBUG"
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### Performance Tuning
|
|
468
|
+
|
|
469
|
+
```python
|
|
470
|
+
# Increase buffer size for high-throughput scenarios
|
|
471
|
+
server = Server(buffer_size=65536)
|
|
472
|
+
client = Client("token", buffer_size=65536, threads=8)
|
|
473
|
+
|
|
474
|
+
# Enable fast open for lower latency
|
|
475
|
+
server = Server(fast_open=True)
|
|
476
|
+
client = Client("token", fast_open=True)
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
## Contributing
|
|
480
|
+
|
|
481
|
+
We welcome contributions! Please see the main [LinkSocks repository](https://github.com/linksocks/linksocks) for contribution guidelines.
|
|
482
|
+
|
|
483
|
+
## License
|
|
484
|
+
|
|
485
|
+
This project is licensed under the MIT License.
|
|
486
|
+
|
|
487
|
+
## Links
|
|
488
|
+
|
|
489
|
+
- 📚 [Full Documentation](https://linksocks.github.io/linksocks/)
|
|
490
|
+
- 🐛 [Issue Tracker](https://github.com/linksocks/linksocks/issues)
|
|
491
|
+
- 💬 [Discussions](https://github.com/linksocks/linksocks/discussions)
|
|
492
|
+
- 📦 [PyPI Package](https://pypi.org/project/linksocks/)
|
|
493
|
+
- 🐳 [Docker Hub](https://hub.docker.com/r/jackzzs/linksocks)
|