simple-proxy 0.0.28__tar.gz → 0.0.30__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.
Files changed (53) hide show
  1. {simple_proxy-0.0.28/simple_proxy.egg-info → simple_proxy-0.0.30}/PKG-INFO +25 -40
  2. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/README.md +23 -38
  3. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/pyproject.toml +2 -2
  4. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/__main__.py +7 -4
  5. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/handler/proxy_channel_handler.py +3 -1
  6. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/handler/shell_channel_handler.py +0 -16
  7. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/run.py +5 -0
  8. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/utils/stringutils.py +4 -0
  9. {simple_proxy-0.0.28 → simple_proxy-0.0.30/simple_proxy.egg-info}/PKG-INFO +25 -40
  10. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy.egg-info/SOURCES.txt +12 -11
  11. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy.egg-info/requires.txt +1 -1
  12. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy.egg-info/top_level.txt +1 -0
  13. simple_proxy-0.0.30/tests/handler/test_echo_channel_handler.py +42 -0
  14. simple_proxy-0.0.30/tests/handler/test_http_proxy_channel_handler.py +258 -0
  15. simple_proxy-0.0.30/tests/handler/test_proxy_channel_handler.py +306 -0
  16. simple_proxy-0.0.30/tests/handler/test_shell_channel_handler.py +202 -0
  17. simple_proxy-0.0.30/tests/handler/test_socks5_proxy_channel_handler.py +361 -0
  18. simple_proxy-0.0.30/tests/test_clients.py +155 -0
  19. simple_proxy-0.0.30/tests/utils/test_certutils.py +25 -0
  20. simple_proxy-0.0.30/tests/utils/test_logutils.py +55 -0
  21. simple_proxy-0.0.30/tests/utils/test_netutils.py +59 -0
  22. {simple_proxy-0.0.28/tests → simple_proxy-0.0.30/tests/utils}/test_osutils.py +0 -7
  23. simple_proxy-0.0.30/tests/utils/test_proxyutils.py +128 -0
  24. {simple_proxy-0.0.28/tests → simple_proxy-0.0.30/tests/utils}/test_stringutils.py +8 -1
  25. simple_proxy-0.0.28/tests/test_certutils.py +0 -23
  26. simple_proxy-0.0.28/tests/test_clients.py +0 -138
  27. simple_proxy-0.0.28/tests/test_echo_channel_handler.py +0 -46
  28. simple_proxy-0.0.28/tests/test_http_proxy_channel_handler.py +0 -255
  29. simple_proxy-0.0.28/tests/test_logutils.py +0 -53
  30. simple_proxy-0.0.28/tests/test_netutils.py +0 -60
  31. simple_proxy-0.0.28/tests/test_proxy_channel_handler.py +0 -308
  32. simple_proxy-0.0.28/tests/test_proxyutils.py +0 -132
  33. simple_proxy-0.0.28/tests/test_socks5_proxy_channel_handler.py +0 -391
  34. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/LICENSE +0 -0
  35. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/setup.cfg +0 -0
  36. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/__init__.py +0 -0
  37. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/clients.py +0 -0
  38. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/handler/__init__.py +0 -0
  39. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/handler/echo_channel_handler.py +0 -0
  40. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/handler/http_proxy_channel_handler.py +0 -0
  41. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/handler/socks5_proxy_channel_handler.py +0 -0
  42. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/utils/__init__.py +0 -0
  43. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/utils/certutils.py +0 -0
  44. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/utils/logutils.py +0 -0
  45. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/utils/netutils.py +0 -0
  46. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/utils/osutils.py +0 -0
  47. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/utils/proxyutils.py +0 -0
  48. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/utils/tlsutils.py +0 -0
  49. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy/version.py +0 -0
  50. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy.egg-info/dependency_links.txt +0 -0
  51. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/simple_proxy.egg-info/entry_points.txt +0 -0
  52. {simple_proxy-0.0.28 → simple_proxy-0.0.30}/tests/test_run.py +0 -0
  53. {simple_proxy-0.0.28/tests → simple_proxy-0.0.30/tests/utils}/test_tlsutils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simple_proxy
3
- Version: 0.0.28
3
+ Version: 0.0.30
4
4
  Summary: A simple NIO proxy tool
5
5
  Home-page: https://github.com/ruanhao/simple-proxy
6
6
  Author-email: Hao Ruan <ruanhao1116@gmail.com>
@@ -26,7 +26,7 @@ Requires-Python: <4,>=3.7
26
26
  Description-Content-Type: text/markdown
27
27
  License-File: LICENSE
28
28
  Requires-Dist: click-option-group
29
- Requires-Dist: py-netty>=1.0.5
29
+ Requires-Dist: py-netty>=1.0.8
30
30
  Requires-Dist: cryptography>=42.0.0
31
31
  Requires-Dist: attrs>=22.1.0
32
32
  Provides-Extra: dev
@@ -43,6 +43,7 @@ Dynamic: license-file
43
43
 
44
44
  [![CI](https://github.com/ruanhao/simple-proxy/actions/workflows/ci.yml/badge.svg)](https://github.com/ruanhao/simple-proxy/actions/workflows/ci.yml)
45
45
  [![codecov](https://codecov.io/github/ruanhao/simple-proxy/graph/badge.svg?token=812EM2WL0L)](https://codecov.io/github/ruanhao/simple-proxy)
46
+ ![PyPI - Downloads](https://img.shields.io/pypi/dm/simple-proxy)
46
47
 
47
48
 
48
49
 
@@ -69,69 +70,53 @@ pip install simple-proxy -U
69
70
  Usage: simple-proxy [OPTIONS]
70
71
 
71
72
  Options:
72
- Common configuration: Configuration for local/remote
73
- endpoints
74
- -l, --listening-host TEXT Listening server address
75
- [default: localhost]
73
+ Common configuration: Configuration for local/remote endpoints
74
+ -l, --listening-host TEXT Listening server address [default: localhost]
76
75
  -lp, --listening-port INTEGER
77
76
  Listening port [default: 8080]
78
77
  -g, --global Listening on all interfaces
79
78
  -r, --remote-host TEXT Remote host [default: localhost]
80
79
  -rp, --remote-port INTEGER Remote port [default: 80]
81
- -s, --tls Denote remote is listening on
82
- secure port
80
+ -s, --tls Denote remote is listening on secure port
83
81
  -ss Listening on secure port
84
82
  TCP proxy configuration: Configuration for TCP proxy mode
85
83
  --read-delay-millis INTEGER Read delay(ms) [default: 0]
86
84
  --write-delay-millis INTEGER Write delay(ms) [default: 0]
85
+ -sni, --server-name-indication TEXT
86
+ Server Name Indication(SNI) for TLS connection to remote server
87
87
  Thread configuration: Configuration for thread
88
- --workers INTEGER Number of worker threads
89
- [default: 1]
90
- --proxy-workers INTEGER Number of proxy threads [default:
91
- 1]
88
+ --workers INTEGER Number of worker threads [default: 1]
89
+ --proxy-workers INTEGER Number of proxy threads [default: 1]
92
90
  Traffic dump configuration: Configuration for traffic dump
93
91
  -c, --tcp-flow Dump tcp flow on to console
94
92
  -f, --save-tcp-flow Save tcp flow to file
95
- TLS certificate configuration:
93
+ TLS certificate configuration:
96
94
  Configuration for TLS certificate
97
95
  -kf, --key-file PATH Key file for local server
98
96
  -cf, --cert-file PATH Certificate file for local server
99
- --alpn Set ALPN protocol as [h2,
100
- http/1.1]
101
- Traffic monitor configuration:
97
+ --alpn Set ALPN protocol as [h2, http/1.1]
98
+ Traffic monitor configuration:
102
99
  Configuration for traffic monitor
103
- -m, --monitor Print speed info to console for
104
- established connection
100
+ -m, --monitor Print speed info to console for established connection
105
101
  -mi, --monitor-interval INTEGER
106
- Speed monitor interval(seconds)
107
- [default: 3]
108
- TLS Disguise configuration: Configuration for protection
109
- against unwanted inspection
102
+ Speed monitor interval(seconds) [default: 3]
103
+ TLS Disguise configuration: Configuration for protection against unwanted inspection
110
104
  -dti, --disguise-tls-ip TEXT Disguised upstream TLS IP
111
105
  -dtp, --disguise-tls-port INTEGER
112
- Disguised upstream TLS port
113
- [default: 443]
114
- --run-disguise-tls-server Run builtin disguise TLS server
115
- without specifying external one
116
- -wl, --white-list TEXT IP White list for legal incoming
117
- TLS connections (comma separated)
118
- Proxy configuration: Configuration for application
119
- proxies
106
+ Disguised upstream TLS port [default: 443]
107
+ --run-disguise-tls-server Run builtin disguise TLS server without specifying external one
108
+ -wl, --white-list TEXT IP White list for legal incoming TLS connections (comma separated)
109
+ Proxy configuration: Configuration for application proxies
120
110
  -e, --echo-proxy Run as Echo server
121
111
  --shell-proxy Run as shell proxy server
122
112
  --http-proxy Run as HTTP proxy server
123
113
  --socks5-proxy Run as SOCKS5 proxy server
124
- --proxy-username TEXT Proxy username for HTTP/SOCKS5
125
- proxy
126
- --proxy-password TEXT Proxy password for HTTP/SOCKS5
127
- proxy
114
+ --proxy-username TEXT Proxy username for HTTP/SOCKS5 proxy
115
+ --proxy-password TEXT Proxy password for HTTP/SOCKS5 proxy
128
116
  -t, --proxy-transform <TEXT INTEGER TEXT INTEGER>...
129
- List of target
130
- transformations(origin_host,
131
- origin_port, transformed_host,
132
- transformed_port) for HTTP/SOCKS5
133
- proxy
134
- Misc configuration:
117
+ List of target transformations(origin_host, origin_port, transformed_host,
118
+ transformed_port) for HTTP/SOCKS5 proxy
119
+ Misc configuration:
135
120
  -v, --verbose
136
121
  --log-file PATH Log file
137
122
  --version Show the version and exit.
@@ -2,6 +2,7 @@
2
2
 
3
3
  [![CI](https://github.com/ruanhao/simple-proxy/actions/workflows/ci.yml/badge.svg)](https://github.com/ruanhao/simple-proxy/actions/workflows/ci.yml)
4
4
  [![codecov](https://codecov.io/github/ruanhao/simple-proxy/graph/badge.svg?token=812EM2WL0L)](https://codecov.io/github/ruanhao/simple-proxy)
5
+ ![PyPI - Downloads](https://img.shields.io/pypi/dm/simple-proxy)
5
6
 
6
7
 
7
8
 
@@ -28,69 +29,53 @@ pip install simple-proxy -U
28
29
  Usage: simple-proxy [OPTIONS]
29
30
 
30
31
  Options:
31
- Common configuration: Configuration for local/remote
32
- endpoints
33
- -l, --listening-host TEXT Listening server address
34
- [default: localhost]
32
+ Common configuration: Configuration for local/remote endpoints
33
+ -l, --listening-host TEXT Listening server address [default: localhost]
35
34
  -lp, --listening-port INTEGER
36
35
  Listening port [default: 8080]
37
36
  -g, --global Listening on all interfaces
38
37
  -r, --remote-host TEXT Remote host [default: localhost]
39
38
  -rp, --remote-port INTEGER Remote port [default: 80]
40
- -s, --tls Denote remote is listening on
41
- secure port
39
+ -s, --tls Denote remote is listening on secure port
42
40
  -ss Listening on secure port
43
41
  TCP proxy configuration: Configuration for TCP proxy mode
44
42
  --read-delay-millis INTEGER Read delay(ms) [default: 0]
45
43
  --write-delay-millis INTEGER Write delay(ms) [default: 0]
44
+ -sni, --server-name-indication TEXT
45
+ Server Name Indication(SNI) for TLS connection to remote server
46
46
  Thread configuration: Configuration for thread
47
- --workers INTEGER Number of worker threads
48
- [default: 1]
49
- --proxy-workers INTEGER Number of proxy threads [default:
50
- 1]
47
+ --workers INTEGER Number of worker threads [default: 1]
48
+ --proxy-workers INTEGER Number of proxy threads [default: 1]
51
49
  Traffic dump configuration: Configuration for traffic dump
52
50
  -c, --tcp-flow Dump tcp flow on to console
53
51
  -f, --save-tcp-flow Save tcp flow to file
54
- TLS certificate configuration:
52
+ TLS certificate configuration:
55
53
  Configuration for TLS certificate
56
54
  -kf, --key-file PATH Key file for local server
57
55
  -cf, --cert-file PATH Certificate file for local server
58
- --alpn Set ALPN protocol as [h2,
59
- http/1.1]
60
- Traffic monitor configuration:
56
+ --alpn Set ALPN protocol as [h2, http/1.1]
57
+ Traffic monitor configuration:
61
58
  Configuration for traffic monitor
62
- -m, --monitor Print speed info to console for
63
- established connection
59
+ -m, --monitor Print speed info to console for established connection
64
60
  -mi, --monitor-interval INTEGER
65
- Speed monitor interval(seconds)
66
- [default: 3]
67
- TLS Disguise configuration: Configuration for protection
68
- against unwanted inspection
61
+ Speed monitor interval(seconds) [default: 3]
62
+ TLS Disguise configuration: Configuration for protection against unwanted inspection
69
63
  -dti, --disguise-tls-ip TEXT Disguised upstream TLS IP
70
64
  -dtp, --disguise-tls-port INTEGER
71
- Disguised upstream TLS port
72
- [default: 443]
73
- --run-disguise-tls-server Run builtin disguise TLS server
74
- without specifying external one
75
- -wl, --white-list TEXT IP White list for legal incoming
76
- TLS connections (comma separated)
77
- Proxy configuration: Configuration for application
78
- proxies
65
+ Disguised upstream TLS port [default: 443]
66
+ --run-disguise-tls-server Run builtin disguise TLS server without specifying external one
67
+ -wl, --white-list TEXT IP White list for legal incoming TLS connections (comma separated)
68
+ Proxy configuration: Configuration for application proxies
79
69
  -e, --echo-proxy Run as Echo server
80
70
  --shell-proxy Run as shell proxy server
81
71
  --http-proxy Run as HTTP proxy server
82
72
  --socks5-proxy Run as SOCKS5 proxy server
83
- --proxy-username TEXT Proxy username for HTTP/SOCKS5
84
- proxy
85
- --proxy-password TEXT Proxy password for HTTP/SOCKS5
86
- proxy
73
+ --proxy-username TEXT Proxy username for HTTP/SOCKS5 proxy
74
+ --proxy-password TEXT Proxy password for HTTP/SOCKS5 proxy
87
75
  -t, --proxy-transform <TEXT INTEGER TEXT INTEGER>...
88
- List of target
89
- transformations(origin_host,
90
- origin_port, transformed_host,
91
- transformed_port) for HTTP/SOCKS5
92
- proxy
93
- Misc configuration:
76
+ List of target transformations(origin_host, origin_port, transformed_host,
77
+ transformed_port) for HTTP/SOCKS5 proxy
78
+ Misc configuration:
94
79
  -v, --verbose
95
80
  --log-file PATH Log file
96
81
  --version Show the version and exit.
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
 
6
6
  [project]
7
7
  name = "simple_proxy"
8
- version = "0.0.28"
8
+ version = "0.0.30"
9
9
  description = "A simple NIO proxy tool"
10
10
  readme = "README.md"
11
11
  requires-python = ">=3.7, <4"
@@ -17,7 +17,7 @@ keywords = ["network", "tcp", "non-blocking", "proxy"]
17
17
 
18
18
  dependencies = [
19
19
  "click-option-group",
20
- "py-netty>=1.0.5",
20
+ "py-netty>=1.0.8",
21
21
  "cryptography>=42.0.0",
22
22
  "attrs>=22.1.0",
23
23
  ]
@@ -16,7 +16,7 @@ logger = logging.getLogger(__name__)
16
16
  ))
17
17
  @optgroup.group('Common configuration', help='Configuration for local/remote endpoints')
18
18
  @optgroup.option('--listening-host', '-l', 'local_server', default='localhost', help='Listening server address', show_default=True)
19
- @optgroup.option('--listening-port', '-lp', 'local_port', type=int, default=8080, help='Listening port', show_default=True)
19
+ @optgroup.option('--listening-port', '-lp', '-p', 'local_port', type=int, default=8080, help='Listening port', show_default=True)
20
20
  @optgroup.option('--global', '-g', 'using_global', is_flag=True, help='Listening on all interfaces')
21
21
  @optgroup.option('--remote-host', '-r', 'remote_server', default='localhost', help='Remote host', show_default=True)
22
22
  @optgroup.option('--remote-port', '-rp', type=int, default=80, help='Remote port', show_default=True)
@@ -25,6 +25,7 @@ logger = logging.getLogger(__name__)
25
25
  @optgroup.group('TCP proxy configuration', help='Configuration for TCP proxy mode')
26
26
  @optgroup.option('--read-delay-millis', type=int, help='Read delay(ms)', default=0, show_default=True)
27
27
  @optgroup.option('--write-delay-millis', type=int, help='Write delay(ms)', default=0, show_default=True)
28
+ @optgroup.option('--server-name-indication', '-sni', help='Server Name Indication(SNI) for TLS connection to remote server')
28
29
  #
29
30
  @optgroup.group('Thread configuration', help='Configuration for thread')
30
31
  @optgroup.option('--workers', type=int, default=1, help='Number of worker threads', show_default=True)
@@ -64,9 +65,11 @@ logger = logging.getLogger(__name__)
64
65
  @click.version_option(prog_name='Simple Proxy', version=__version__)
65
66
  def _cli(verbose, log_file: click.Path, **kwargs):
66
67
  setup_logging(log_file, logging.INFO if verbose == 0 else logging.DEBUG)
67
- if verbose:
68
- logger.setLevel(logging.DEBUG)
69
- logging.getLogger('simple_proxy.utils').setLevel(logging.DEBUG)
68
+ if verbose < 2:
69
+ logger.setLevel(logging.WARNING)
70
+ for name in ("py_netty", "simple_proxy.utils"):
71
+ logging.getLogger(name).setLevel(logging.WARNING)
72
+
70
73
  run_proxy(**kwargs)
71
74
 
72
75
 
@@ -24,6 +24,7 @@ class ProxyChannelHandler(LoggingChannelHandler):
24
24
  alpn: bool = False,
25
25
  read_delay_millis: int = 0,
26
26
  write_delay_millis: int = 0,
27
+ sni: str | None = None,
27
28
  ):
28
29
  self._remote_host = remote_host
29
30
  self._remote_port = remote_port
@@ -42,6 +43,7 @@ class ProxyChannelHandler(LoggingChannelHandler):
42
43
  self._write_delay_millis = write_delay_millis
43
44
  self._unwritable_seconds: float = None # noqa
44
45
  self.raddr: tuple[str, int] = None # noqa
46
+ self.sni = sni
45
47
 
46
48
  def _client_channel(self, ctx0, ip, port):
47
49
 
@@ -77,7 +79,7 @@ class ProxyChannelHandler(LoggingChannelHandler):
77
79
  tls=self._tls,
78
80
  verify=False,
79
81
  ssl_context_cb=alpn_ssl_context_cb if self._alpn else None,
80
- ).connect(ip, port, True).sync().channel()
82
+ ).connect(ip, port, True, self.sni).sync().channel()
81
83
  set_keepalive(self._client.socket())
82
84
  return self._client
83
85
 
@@ -77,22 +77,6 @@ class ShellChannelHandler(LoggingChannelHandler):
77
77
  self._shell_stdin_fd = master_fd
78
78
  submit_daemon_thread(self.handle_read_output, ctx, master_fd)
79
79
 
80
- def _setup_linux_shell0(self, ctx):
81
- my_env = os.environ.copy()
82
- i_r, i_w = os.pipe()
83
- o_r, o_w = os.pipe()
84
- self._process = subprocess.Popen(
85
- [shutil.which('bash'), '-li'],
86
- stdin=i_r,
87
- stdout=o_w,
88
- stderr=o_w,
89
- bufsize=-1,
90
- start_new_session=True,
91
- env=my_env
92
- )
93
- self._shell_stdin_fd = i_w
94
- submit_daemon_thread(self.handle_read_output, ctx, o_r)
95
-
96
80
  def channel_active(self, ctx):
97
81
  super().channel_active(ctx)
98
82
  local_socket = ctx.channel().socket()
@@ -20,6 +20,7 @@ from .utils import (
20
20
  alpn_ssl_context_cb,
21
21
  random_sentence,
22
22
  )
23
+ from .utils.stringutils import is_ip_address
23
24
 
24
25
 
25
26
  class MyHttpHandler(http.server.BaseHTTPRequestHandler):
@@ -52,6 +53,7 @@ def run_proxy(
52
53
  proxy_username=None, proxy_password=None,
53
54
  shell_proxy=False,
54
55
  read_delay_millis=0, write_delay_millis=0,
56
+ server_name_indication: str | None = None,
55
57
  workers=1, proxy_workers=1,
56
58
  as_echo_server=False,
57
59
  ):
@@ -168,6 +170,7 @@ def run_proxy(
168
170
  alpn=alpn,
169
171
  read_delay_millis=read_delay_millis,
170
172
  write_delay_millis=write_delay_millis,
173
+ sni=server_name_indication,
171
174
  ),
172
175
  certfile=cf,
173
176
  keyfile=kf,
@@ -176,6 +179,8 @@ def run_proxy(
176
179
  disguise = f"https://{disguise_tls_ip}:{disguise_tls_port}" if disguise_tls_ip else 'n/a'
177
180
  pstderr(f"Proxy server started listening: {local_server}:{local_port}{'(TLS)' if ss else ''} => {remote_server}:{remote_port}{'(TLS)' if tls else ''} ...")
178
181
  pstderr(f"console:{content}, file:{to_file}, disguise:{disguise}, whitelist:{white_list0 or '*'}")
182
+ if is_ip_address(remote_server) and tls and not server_name_indication:
183
+ pstderr("[WARN] Direct IP address is used as remote TLS server, it's recommended to specify SNI using '--server-name-indication' option!")
179
184
 
180
185
  if monitor:
181
186
  spawn_clients_monitor(monitor_interval)
@@ -66,3 +66,7 @@ def check_ip_patterns(patterns: list[str], s: str) -> bool:
66
66
  _get_logger().debug(f"pattern {pattern} matched {s}")
67
67
  return True
68
68
  return False
69
+
70
+ def is_ip_address(s: str) -> bool:
71
+ ip_pattern = re.compile(r'^(\d{1,3}\.){3}\d{1,3}$')
72
+ return bool(ip_pattern.match(s))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simple_proxy
3
- Version: 0.0.28
3
+ Version: 0.0.30
4
4
  Summary: A simple NIO proxy tool
5
5
  Home-page: https://github.com/ruanhao/simple-proxy
6
6
  Author-email: Hao Ruan <ruanhao1116@gmail.com>
@@ -26,7 +26,7 @@ Requires-Python: <4,>=3.7
26
26
  Description-Content-Type: text/markdown
27
27
  License-File: LICENSE
28
28
  Requires-Dist: click-option-group
29
- Requires-Dist: py-netty>=1.0.5
29
+ Requires-Dist: py-netty>=1.0.8
30
30
  Requires-Dist: cryptography>=42.0.0
31
31
  Requires-Dist: attrs>=22.1.0
32
32
  Provides-Extra: dev
@@ -43,6 +43,7 @@ Dynamic: license-file
43
43
 
44
44
  [![CI](https://github.com/ruanhao/simple-proxy/actions/workflows/ci.yml/badge.svg)](https://github.com/ruanhao/simple-proxy/actions/workflows/ci.yml)
45
45
  [![codecov](https://codecov.io/github/ruanhao/simple-proxy/graph/badge.svg?token=812EM2WL0L)](https://codecov.io/github/ruanhao/simple-proxy)
46
+ ![PyPI - Downloads](https://img.shields.io/pypi/dm/simple-proxy)
46
47
 
47
48
 
48
49
 
@@ -69,69 +70,53 @@ pip install simple-proxy -U
69
70
  Usage: simple-proxy [OPTIONS]
70
71
 
71
72
  Options:
72
- Common configuration: Configuration for local/remote
73
- endpoints
74
- -l, --listening-host TEXT Listening server address
75
- [default: localhost]
73
+ Common configuration: Configuration for local/remote endpoints
74
+ -l, --listening-host TEXT Listening server address [default: localhost]
76
75
  -lp, --listening-port INTEGER
77
76
  Listening port [default: 8080]
78
77
  -g, --global Listening on all interfaces
79
78
  -r, --remote-host TEXT Remote host [default: localhost]
80
79
  -rp, --remote-port INTEGER Remote port [default: 80]
81
- -s, --tls Denote remote is listening on
82
- secure port
80
+ -s, --tls Denote remote is listening on secure port
83
81
  -ss Listening on secure port
84
82
  TCP proxy configuration: Configuration for TCP proxy mode
85
83
  --read-delay-millis INTEGER Read delay(ms) [default: 0]
86
84
  --write-delay-millis INTEGER Write delay(ms) [default: 0]
85
+ -sni, --server-name-indication TEXT
86
+ Server Name Indication(SNI) for TLS connection to remote server
87
87
  Thread configuration: Configuration for thread
88
- --workers INTEGER Number of worker threads
89
- [default: 1]
90
- --proxy-workers INTEGER Number of proxy threads [default:
91
- 1]
88
+ --workers INTEGER Number of worker threads [default: 1]
89
+ --proxy-workers INTEGER Number of proxy threads [default: 1]
92
90
  Traffic dump configuration: Configuration for traffic dump
93
91
  -c, --tcp-flow Dump tcp flow on to console
94
92
  -f, --save-tcp-flow Save tcp flow to file
95
- TLS certificate configuration:
93
+ TLS certificate configuration:
96
94
  Configuration for TLS certificate
97
95
  -kf, --key-file PATH Key file for local server
98
96
  -cf, --cert-file PATH Certificate file for local server
99
- --alpn Set ALPN protocol as [h2,
100
- http/1.1]
101
- Traffic monitor configuration:
97
+ --alpn Set ALPN protocol as [h2, http/1.1]
98
+ Traffic monitor configuration:
102
99
  Configuration for traffic monitor
103
- -m, --monitor Print speed info to console for
104
- established connection
100
+ -m, --monitor Print speed info to console for established connection
105
101
  -mi, --monitor-interval INTEGER
106
- Speed monitor interval(seconds)
107
- [default: 3]
108
- TLS Disguise configuration: Configuration for protection
109
- against unwanted inspection
102
+ Speed monitor interval(seconds) [default: 3]
103
+ TLS Disguise configuration: Configuration for protection against unwanted inspection
110
104
  -dti, --disguise-tls-ip TEXT Disguised upstream TLS IP
111
105
  -dtp, --disguise-tls-port INTEGER
112
- Disguised upstream TLS port
113
- [default: 443]
114
- --run-disguise-tls-server Run builtin disguise TLS server
115
- without specifying external one
116
- -wl, --white-list TEXT IP White list for legal incoming
117
- TLS connections (comma separated)
118
- Proxy configuration: Configuration for application
119
- proxies
106
+ Disguised upstream TLS port [default: 443]
107
+ --run-disguise-tls-server Run builtin disguise TLS server without specifying external one
108
+ -wl, --white-list TEXT IP White list for legal incoming TLS connections (comma separated)
109
+ Proxy configuration: Configuration for application proxies
120
110
  -e, --echo-proxy Run as Echo server
121
111
  --shell-proxy Run as shell proxy server
122
112
  --http-proxy Run as HTTP proxy server
123
113
  --socks5-proxy Run as SOCKS5 proxy server
124
- --proxy-username TEXT Proxy username for HTTP/SOCKS5
125
- proxy
126
- --proxy-password TEXT Proxy password for HTTP/SOCKS5
127
- proxy
114
+ --proxy-username TEXT Proxy username for HTTP/SOCKS5 proxy
115
+ --proxy-password TEXT Proxy password for HTTP/SOCKS5 proxy
128
116
  -t, --proxy-transform <TEXT INTEGER TEXT INTEGER>...
129
- List of target
130
- transformations(origin_host,
131
- origin_port, transformed_host,
132
- transformed_port) for HTTP/SOCKS5
133
- proxy
134
- Misc configuration:
117
+ List of target transformations(origin_host, origin_port, transformed_host,
118
+ transformed_port) for HTTP/SOCKS5 proxy
119
+ Misc configuration:
135
120
  -v, --verbose
136
121
  --log-file PATH Log file
137
122
  --version Show the version and exit.
@@ -27,16 +27,17 @@ simple_proxy/utils/osutils.py
27
27
  simple_proxy/utils/proxyutils.py
28
28
  simple_proxy/utils/stringutils.py
29
29
  simple_proxy/utils/tlsutils.py
30
- tests/test_certutils.py
31
30
  tests/test_clients.py
32
- tests/test_echo_channel_handler.py
33
- tests/test_http_proxy_channel_handler.py
34
- tests/test_logutils.py
35
- tests/test_netutils.py
36
- tests/test_osutils.py
37
- tests/test_proxy_channel_handler.py
38
- tests/test_proxyutils.py
39
31
  tests/test_run.py
40
- tests/test_socks5_proxy_channel_handler.py
41
- tests/test_stringutils.py
42
- tests/test_tlsutils.py
32
+ tests/handler/test_echo_channel_handler.py
33
+ tests/handler/test_http_proxy_channel_handler.py
34
+ tests/handler/test_proxy_channel_handler.py
35
+ tests/handler/test_shell_channel_handler.py
36
+ tests/handler/test_socks5_proxy_channel_handler.py
37
+ tests/utils/test_certutils.py
38
+ tests/utils/test_logutils.py
39
+ tests/utils/test_netutils.py
40
+ tests/utils/test_osutils.py
41
+ tests/utils/test_proxyutils.py
42
+ tests/utils/test_stringutils.py
43
+ tests/utils/test_tlsutils.py
@@ -1,5 +1,5 @@
1
1
  click-option-group
2
- py-netty>=1.0.5
2
+ py-netty>=1.0.8
3
3
  cryptography>=42.0.0
4
4
  attrs>=22.1.0
5
5
 
@@ -5,3 +5,4 @@ img
5
5
  simple_proxy
6
6
  test_dir
7
7
  tests
8
+ venv
@@ -0,0 +1,42 @@
1
+ from simple_proxy.handler.echo_channel_handler import EchoChannelHandler
2
+ from py_netty import EventLoopGroup
3
+ from simple_proxy.clients import get_clients
4
+ import pytest
5
+
6
+
7
+ @pytest.fixture(scope='function', autouse=False)
8
+ def ctx_mocker(mocker):
9
+ return mocker.MagicMock()
10
+
11
+
12
+ class TestChannelRead:
13
+
14
+ def test_with_client(self, mocker, ctx_mocker):
15
+ raddr = ('127.0.0.1', 8080)
16
+ ctx_mocker.channel.return_value.channelinfo.return_value.peername = raddr
17
+ handler = EchoChannelHandler(EventLoopGroup(), tls=False)
18
+
19
+ client_mocker = mocker.MagicMock()
20
+ get_clients()[raddr] = client_mocker
21
+ handler.channel_read(ctx_mocker, b'123')
22
+ ctx_mocker.channel().write.assert_called_once_with(b'123')
23
+ client_mocker.read.assert_called_once_with(3)
24
+ client_mocker.write.assert_called_once_with(3)
25
+
26
+ def test_without_client(self, ctx_mocker):
27
+ raddr = ('127.0.0.1', 8080)
28
+ ctx_mocker.channel.return_value.channelinfo.return_value.peername = raddr
29
+ handler = EchoChannelHandler(EventLoopGroup(), tls=False)
30
+
31
+ get_clients().clear()
32
+ handler.channel_read(ctx_mocker, b'123')
33
+ assert ctx_mocker.channel.called
34
+ ctx_mocker.channel().write.assert_called_once_with(b'123')
35
+
36
+ def test_empty(self, ctx_mocker):
37
+ raddr = ('127.0.0.1', 8080)
38
+ ctx_mocker.channel.return_value.channelinfo.return_value.peername = raddr
39
+
40
+ handler = EchoChannelHandler(EventLoopGroup(), tls=False)
41
+ handler.channel_read(ctx_mocker, b'')
42
+ assert not ctx_mocker.channel.called