Add DNS, HTTP, Socks4/4a tests

This commit is contained in:
zonyitoo
2020-11-08 04:31:39 +08:00
committed by ty
parent f43ee3e958
commit 3223ff16c9
10 changed files with 316 additions and 30 deletions

90
tests/dns.rs Normal file
View File

@@ -0,0 +1,90 @@
#![cfg(feature = "local-dns-relay")]
use std::time::Duration;
use byteorder::{BigEndian, ByteOrder};
use tokio::{
net::{TcpStream, UdpSocket},
prelude::*,
time,
};
use shadowsocks::{
config::{Config, ConfigType},
run_local,
run_server,
};
#[tokio::test]
async fn dns_relay() {
let _ = env_logger::try_init();
let mut local_config = Config::load_from_str(
r#"{
"local_port": 6110,
"local_address": "127.0.0.1",
"server": "127.0.0.1",
"server_port": 6120,
"password": "password",
"method": "aes-256-gcm"
}"#,
ConfigType::DnsLocal,
)
.unwrap();
local_config.local_dns_addr = Some("114.114.114.114:53".parse().unwrap());
local_config.remote_dns_addr = Some("8.8.8.8:53".parse().unwrap());
let server_config = Config::load_from_str(
r#"{
"server": "127.0.0.1",
"server_port": 6120,
"password": "password",
"method": "aes-256-gcm",
"mode": "tcp_and_udp"
}"#,
ConfigType::Server,
)
.unwrap();
tokio::spawn(run_local(local_config));
tokio::spawn(run_server(server_config));
time::sleep(Duration::from_secs(1)).await;
// Query firefox.com, TransactionID: 0x1234
static DNS_QUERY: &[u8] = b"\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07firefox\x03com\x00\x00\x01\x00\x01";
// 1. DoT
{
let mut c = TcpStream::connect("127.0.0.1:6110").await.unwrap();
let mut len_buf = [0u8; 2];
BigEndian::write_u16(&mut len_buf, DNS_QUERY.len() as u16);
c.write_all(&len_buf).await.unwrap();
c.write_all(DNS_QUERY).await.unwrap();
c.flush().await.unwrap();
c.read_exact(&mut len_buf).await.unwrap();
let resp_len = BigEndian::read_u16(&len_buf);
let mut buf = vec![0u8; resp_len as usize];
c.read_exact(&mut buf).await.unwrap();
assert!(buf.starts_with(b"\x12\x34"));
}
// 2. DoU
{
let c = UdpSocket::bind("0.0.0.0:0").await.unwrap();
c.send_to(DNS_QUERY, "127.0.0.1:6110").await.unwrap();
let mut buf = [0u8; 65536];
let n = c.recv(&mut buf).await.unwrap();
assert!(n >= 12);
let pkt = &buf[..n];
assert_eq!(&pkt[..2], b"\x12\x34");
}
}

76
tests/http.rs Normal file
View File

@@ -0,0 +1,76 @@
#![cfg(feature = "local-http")]
use std::time::Duration;
use tokio::{net::TcpStream, prelude::*, time};
use shadowsocks::{
config::{Config, ConfigType},
run_local,
run_server,
};
#[tokio::test]
async fn http_proxy() {
let _ = env_logger::try_init();
let local_config = Config::load_from_str(
r#"{
"local_port": 5110,
"local_address": "127.0.0.1",
"server": "127.0.0.1",
"server_port": 5120,
"password": "password",
"method": "aes-256-gcm"
}"#,
ConfigType::HttpLocal,
)
.unwrap();
let server_config = Config::load_from_str(
r#"{
"server": "127.0.0.1",
"server_port": 5120,
"password": "password",
"method": "aes-256-gcm"
}"#,
ConfigType::Server,
)
.unwrap();
tokio::spawn(run_local(local_config));
tokio::spawn(run_server(server_config));
time::sleep(Duration::from_secs(1)).await;
{
let mut c = TcpStream::connect("127.0.0.1:5110").await.unwrap();
c.write_all(b"GET http://www.example.com/ HTTP/1.0\r\nHost: www.example.com\r\nAccept: */*\r\n\r\n")
.await
.unwrap();
c.flush().await.unwrap();
let mut buf = Vec::new();
c.read_to_end(&mut buf).await.unwrap();
assert!(buf.starts_with(b"HTTP/1.0 200 OK\r\n"));
}
{
let mut c = TcpStream::connect("127.0.0.1:5110").await.unwrap();
c.write_all(b"CONNECT http://www.example.com/ HTTP/1.0\r\n\r\n")
.await
.unwrap();
c.flush().await.unwrap();
c.write_all(b"GET / HTTP/1.0\r\nHost: www.example.com\r\nAccept: */*\r\n\r\n")
.await
.unwrap();
c.flush().await.unwrap();
let mut buf = Vec::new();
c.read_to_end(&mut buf).await.unwrap();
assert!(buf.starts_with(b"HTTP/1.0 200 OK\r\n"));
}
}

110
tests/socks4.rs Normal file
View File

@@ -0,0 +1,110 @@
#![cfg(feature = "local-socks4")]
use std::{
net::{SocketAddr, ToSocketAddrs},
str,
};
use tokio::{
net::TcpStream,
prelude::*,
time::{self, Duration},
};
use shadowsocks::{
config::{Config, ConfigType, ServerAddr, ServerConfig},
crypto::CipherType,
relay::socks4::{Address, Command, HandshakeRequest, HandshakeResponse, ResultCode},
run_local,
run_server,
};
pub struct Socks4TestServer {
local_addr: SocketAddr,
svr_config: Config,
cli_config: Config,
}
impl Socks4TestServer {
pub fn new<S, L>(svr_addr: S, local_addr: L, pwd: &str, method: CipherType) -> Socks4TestServer
where
S: ToSocketAddrs,
L: ToSocketAddrs,
{
let svr_addr = svr_addr.to_socket_addrs().unwrap().next().unwrap();
let local_addr = local_addr.to_socket_addrs().unwrap().next().unwrap();
Socks4TestServer {
local_addr,
svr_config: {
let mut cfg = Config::new(ConfigType::Server);
cfg.server = vec![ServerConfig::basic(svr_addr, pwd.to_owned(), method)];
cfg
},
cli_config: {
let mut cfg = Config::new(ConfigType::Socks4Local);
cfg.local_addr = Some(ServerAddr::from(local_addr));
cfg.server = vec![ServerConfig::basic(svr_addr, pwd.to_owned(), method)];
cfg
},
}
}
pub fn client_addr(&self) -> &SocketAddr {
&self.local_addr
}
pub async fn run(&self) {
let svr_cfg = self.svr_config.clone();
tokio::spawn(run_server(svr_cfg));
let client_cfg = self.cli_config.clone();
tokio::spawn(run_local(client_cfg));
time::sleep(Duration::from_secs(1)).await;
}
}
#[tokio::test]
async fn socks4_relay_connect() {
let _ = env_logger::try_init();
const SERVER_ADDR: &str = "127.0.0.1:7100";
const LOCAL_ADDR: &str = "127.0.0.1:7200";
const PASSWORD: &str = "test-password";
const METHOD: CipherType = CipherType::Aes128Gcm;
let svr = Socks4TestServer::new(SERVER_ADDR, LOCAL_ADDR, PASSWORD, METHOD);
svr.run().await;
static HTTP_REQUEST: &[u8] = b"GET / HTTP/1.0\r\nHost: www.example.com\r\nAccept: */*\r\n\r\n";
let mut c = TcpStream::connect(LOCAL_ADDR).await.unwrap();
let req = HandshakeRequest {
cd: Command::Connect,
dst: Address::from(("www.example.com".to_owned(), 80)),
user_id: Vec::new(),
};
let mut handshake_buf = Vec::new();
req.write_to_buf(&mut handshake_buf);
c.write_all(&handshake_buf).await.unwrap();
c.flush().await.unwrap();
let rsp = HandshakeResponse::read_from(&mut c).await.unwrap();
assert_eq!(rsp.cd, ResultCode::RequestGranted);
c.write_all(HTTP_REQUEST).await.unwrap();
c.flush().await.unwrap();
let mut buf = Vec::new();
c.read_to_end(&mut buf).await.unwrap();
println!("Got reply from server: {}", str::from_utf8(&buf).unwrap());
let http_status = b"HTTP/1.0 200 OK\r\n";
buf.starts_with(http_status);
}

View File

@@ -72,7 +72,7 @@ async fn socks5_relay_stream() {
const LOCAL_ADDR: &str = "127.0.0.1:8200";
const PASSWORD: &str = "test-password";
const METHOD: CipherType = CipherType::Aes128Gcm;
const METHOD: CipherType = CipherType::Aes128Cfb;
let svr = Socks5TestServer::new(SERVER_ADDR, LOCAL_ADDR, PASSWORD, METHOD, false);
svr.run().await;