send error replies

This commit is contained in:
Y. T. Chung
2014-10-23 20:19:31 +08:00
parent b64a52b0ae
commit ad22c1878f
4 changed files with 48 additions and 18 deletions

View File

@@ -26,8 +26,7 @@ pub use self::server::RelayServer;
use std::fmt::{Show, Formatter, FormatError};
use std::io::net::ip::{SocketAddr, Port};
use std::io::TcpStream;
use std::io::net::ip::{Ipv4Addr, Ipv6Addr};
use std::io::net::ip::{Ipv4Addr, Ipv6Addr};
pub mod tcprelay;
// pub mod udprelay;
@@ -145,8 +144,3 @@ pub fn parse_request_header(buf: &[u8]) -> Result<(uint, Sock5AddrType), u8> {
}
}
}
pub fn send_error_reply(stream: &mut TcpStream, err_code: u8) {
let reply = [SOCKS5_VERSION, err_code, 0x00];
stream.write(reply).ok().expect("Error occurs while sending errors");
}

View File

@@ -27,18 +27,20 @@ extern crate log;
use std::sync::Arc;
use std::io::{Listener, TcpListener, Acceptor, TcpStream};
use std::io::{EndOfFile, TimedOut, NotConnected};
use std::io::{EndOfFile, TimedOut, NotConnected,
ConnectionFailed, ConnectionRefused, ConnectionReset, ConnectionAborted};
use std::io::net::ip::Port;
use std::io::net::ip::{Ipv4Addr, Ipv6Addr};
use config::Config;
use relay::Relay;
use relay::{parse_request_header, send_error_reply};
use relay::parse_request_header;
use relay::tcprelay::send_error_reply;
use relay::{SOCKS5_VERSION, SOCKS5_AUTH_METHOD_NONE};
use relay::{SOCKS5_CMD_TCP_CONNECT, SOCKS5_CMD_TCP_BIND, SOCKS5_CMD_UDP_ASSOCIATE};
use relay::{SOCKS5_ADDR_TYPE_IPV6, SOCKS5_ADDR_TYPE_IPV4};
use relay::{SOCKS5_REPLY_COMMAND_NOT_SUPPORTED};
use relay::{SOCKS5_REPLY_COMMAND_NOT_SUPPORTED, SOCKS5_REPLY_HOST_UNREACHABLE, SOCKS5_REPLY_NETWORK_UNREACHABLE};
use relay::SOCKS5_REPLY_SUCCEEDED;
use relay::loadbalancing::server::{LoadBalancer, RoundRobin};
@@ -224,9 +226,21 @@ impl TcpRelayLocal {
(header_buf.slice_to(header_len).to_vec(), addr)
};
let mut remote_stream = TcpStream::connect(server_addr.as_slice(),
server_port)
.ok().expect("Error occurs while connecting to remote server");
let mut remote_stream = match TcpStream::connect(server_addr.as_slice(),
server_port) {
Ok(s) => s,
Err(err) => {
match err.kind {
ConnectionAborted | ConnectionReset | ConnectionRefused | ConnectionFailed => {
send_error_reply(stream, SOCKS5_REPLY_HOST_UNREACHABLE);
},
_ => {
send_error_reply(stream, SOCKS5_REPLY_NETWORK_UNREACHABLE);
}
}
fail!("Failed to connect remote server: {}", err);
}
};
let mut cipher = cipher::with_name(encrypt_method.as_slice(),
password.as_slice().as_bytes())
@@ -262,6 +276,7 @@ impl TcpRelayLocal {
&mut cipher));
},
SOCKS5_CMD_TCP_BIND => {
send_error_reply(stream, SOCKS5_REPLY_COMMAND_NOT_SUPPORTED);
unimplemented!();
},
SOCKS5_CMD_UDP_ASSOCIATE => {

View File

@@ -26,5 +26,13 @@ extern crate log;
extern crate native;
use std::io::TcpStream;
use relay::SOCKS5_VERSION;
pub mod local;
pub mod server;
pub fn send_error_reply(stream: &mut TcpStream, err_code: u8) {
let reply = [SOCKS5_VERSION, err_code, 0x00];
stream.write(reply).ok().expect("Error occurs while sending errors");
}

View File

@@ -32,7 +32,8 @@ use std::io::{EndOfFile, TimedOut};
use config::{Config, SingleServer, MultipleServer};
use relay::Relay;
use relay::{parse_request_header, Sock5SocketAddr, Sock5DomainNameAddr};
use relay::send_error_reply;
use relay::tcprelay::send_error_reply;
use relay::{SOCKS5_REPLY_HOST_UNREACHABLE};
use crypto::cipher;
use crypto::cipher::Cipher;
@@ -194,23 +195,35 @@ impl Relay for TcpRelayServer {
info!("Connecting to {}", addr);
let mut remote_stream = match addr {
Sock5SocketAddr(sockaddr) => {
TcpStream::connect(sockaddr.ip.to_string().as_slice(), sockaddr.port)
.ok().expect("Unable to connect to remote")
match TcpStream::connect(sockaddr.ip.to_string().as_slice(), sockaddr.port) {
Ok(s) => s,
Err(err) => {
send_error_reply(&mut stream, SOCKS5_REPLY_HOST_UNREACHABLE);
fail!("Unable to connect {}: {}", sockaddr, err)
}
}
},
Sock5DomainNameAddr(domainaddr) => {
let addrs = match get_host_addresses(domainaddr.domain_name.as_slice()) {
Ok(ipaddrs) => ipaddrs,
Err(e) => {
send_error_reply(&mut stream, SOCKS5_REPLY_HOST_UNREACHABLE);
fail!("Error occurs while get_host_addresses: {}", e);
}
};
if addrs.len() == 0 {
send_error_reply(&mut stream, SOCKS5_REPLY_HOST_UNREACHABLE);
fail!("Cannot resolve host {}, empty host list", domainaddr.domain_name);
}
TcpRelayServer::connect_remote(addrs, domainaddr.port)
.expect(format!("Unable to resolve {}", domainaddr.domain_name).as_slice())
match TcpRelayServer::connect_remote(addrs, domainaddr.port) {
Some(s) => s,
None => {
send_error_reply(&mut stream, SOCKS5_REPLY_HOST_UNREACHABLE);
fail!("Unable to resolve host {}", domainaddr)
}
}
}
};