@@ -4,20 +4,20 @@ use axum::{Json, extract::Path};
44
55use crate :: error:: { AppError , AppResult } ;
66
7+ const ALLOWED_PROXY_PORTS : & [ u16 ] = & [
8+ 3000 , 3001 , 3002 , 3003 , // React、Next.js
9+ 4000 , 4173 , 4200 , // Angular、Vite 预览
10+ 5000 , 5173 , 5174 , // Vite、Flask
11+ 8000 , 8080 , 8081 , // Django、通用开发服务
12+ ] ;
13+
714/// List open ports on localhost.
815pub async fn list_open_ports ( ) -> Json < Vec < u16 > > {
9- let ports_to_check: Vec < u16 > = vec ! [
10- 3000 , 3001 , 3002 , 3003 , // React, Next.js
11- 4000 , 4173 , 4200 , // Angular, Vite preview
12- 5000 , 5173 , 5174 , // Vite, Flask
13- 8000 , 8080 , 8081 , // Django, generic
14- ] ;
15-
1616 let mut open_ports = Vec :: new ( ) ;
1717
18- for port in ports_to_check {
18+ for port in ALLOWED_PROXY_PORTS {
1919 if std:: net:: TcpStream :: connect ( format ! ( "127.0.0.1:{port}" ) ) . is_ok ( ) {
20- open_ports. push ( port) ;
20+ open_ports. push ( * port) ;
2121 }
2222 }
2323
@@ -36,6 +36,12 @@ pub async fn proxy_to_port_path(
3636 use axum:: body:: Body ;
3737 use axum:: http:: { StatusCode , header} ;
3838
39+ if !is_proxy_port_allowed ( port) {
40+ return Err ( AppError :: Authorization ( format ! (
41+ "Port {port} is not allowed for proxying"
42+ ) ) ) ;
43+ }
44+
3945 let target_url = format ! ( "http://127.0.0.1:{port}/{path}" ) ;
4046
4147 let client = reqwest:: Client :: builder ( )
@@ -79,3 +85,27 @@ pub async fn proxy_to_port_path(
7985 . body ( Body :: from ( body) )
8086 . map_err ( |e| AppError :: Internal ( format ! ( "Failed to build response: {e}" ) ) )
8187}
88+
89+ fn is_proxy_port_allowed ( port : u16 ) -> bool {
90+ ALLOWED_PROXY_PORTS . contains ( & port)
91+ }
92+
93+ #[ cfg( test) ]
94+ mod tests {
95+ use super :: * ;
96+
97+ #[ tokio:: test]
98+ async fn proxy_rejects_non_dev_ports ( ) {
99+ let result = proxy_to_port_path ( Path ( ( 22 , String :: new ( ) ) ) ) . await ;
100+
101+ assert ! ( matches!( result, Err ( AppError :: Authorization ( _) ) ) ) ;
102+ }
103+
104+ #[ test]
105+ fn proxy_allows_only_known_dev_ports ( ) {
106+ assert ! ( is_proxy_port_allowed( 5173 ) ) ;
107+ assert ! ( is_proxy_port_allowed( 8080 ) ) ;
108+ assert ! ( !is_proxy_port_allowed( 22 ) ) ;
109+ assert ! ( !is_proxy_port_allowed( 9200 ) ) ;
110+ }
111+ }
0 commit comments