Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ssl.alpn_port_override (Fixes #171 and #226) #349

Merged
merged 3 commits into from
Mar 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ The NAT config is for transparent proxy. You'll need to [setup iptables rules](h
"alpn": [
"http/1.1"
],
"alpn_port_override": {
"h2": 81
},
"reuse_session": true,
"session_ticket": false,
"session_timeout": 600,
Expand Down Expand Up @@ -216,6 +219,7 @@ The NAT config is for transparent proxy. You'll need to [setup iptables rules](h
- `cipher_tls13`: a cipher list for TLS 1.3 to use
- `prefer_server_cipher`: whether to prefer server cipher list in a connection
- `alpn`: a list of `ALPN` protocols to reply
- `alpn_port_override`: overrides the remote port to the specified value if an `ALPN` is matched. Useful for running NGINX with HTTP/1.1 and HTTP/2 Cleartext on different ports.
- `reuse_session`: whether to reuse `SSL` session
- `session_ticket`: whether to use session tickets for session resumption
- `session_timeout`: if `reuse_session` is set to `true`, specify `SSL` session timeout
Expand Down
3 changes: 3 additions & 0 deletions examples/server.json-example
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
"alpn": [
"http/1.1"
],
"alpn_port_override": {
"h2": 81
},
"reuse_session": true,
"session_ticket": false,
"session_timeout": 600,
Expand Down
24 changes: 17 additions & 7 deletions src/core/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ void Config::populate(const ptree &tree) {
target_addr = tree.get("target_addr", string());
target_port = tree.get("target_port", uint16_t());
map<string, string>().swap(password);
for (auto& item: tree.get_child("password")) {
string p = item.second.get_value<string>();
password[SHA224(p)] = p;
if (tree.get_child_optional("password")) {
for (auto& item: tree.get_child("password")) {
string p = item.second.get_value<string>();
password[SHA224(p)] = p;
}
}
udp_timeout = tree.get("udp_timeout", 60);
log_level = static_cast<Log::Level>(tree.get("log_level", 1));
Expand All @@ -75,10 +77,18 @@ void Config::populate(const ptree &tree) {
ssl.prefer_server_cipher = tree.get("ssl.prefer_server_cipher", true);
ssl.sni = tree.get("ssl.sni", string());
ssl.alpn = "";
for (auto& item: tree.get_child("ssl.alpn")) {
string proto = item.second.get_value<string>();
ssl.alpn += (char)((unsigned char)(proto.length()));
ssl.alpn += proto;
if (tree.get_child_optional("ssl.alpn")) {
for (auto& item: tree.get_child("ssl.alpn")) {
string proto = item.second.get_value<string>();
ssl.alpn += (char)((unsigned char)(proto.length()));
ssl.alpn += proto;
}
}
map<string, uint16_t>().swap(ssl.alpn_port_override);
if (tree.get_child_optional("ssl.alpn_port_override")) {
for (auto& item: tree.get_child("ssl.alpn_port_override")) {
ssl.alpn_port_override[item.first] = item.second.get_value<uint16_t>();
}
}
ssl.reuse_session = tree.get("ssl.reuse_session", true);
ssl.session_ticket = tree.get("ssl.session_ticket", false);
Expand Down
1 change: 1 addition & 0 deletions src/core/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class Config {
bool prefer_server_cipher;
std::string sni;
std::string alpn;
std::map<std::string, uint16_t> alpn_port_override;
bool reuse_session;
bool session_ticket;
long session_timeout;
Expand Down
16 changes: 14 additions & 2 deletions src/session/serversession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,19 @@ void ServerSession::in_recv(const string &data) {
}
}
string query_addr = valid ? req.address.address : config.remote_addr;
string query_port = to_string(valid ? req.address.port : config.remote_port);
string query_port = to_string([&]() {
if (valid) {
return req.address.port;
}
const unsigned char *alpn_out;
unsigned int alpn_len;
SSL_get0_alpn_selected(in_socket.native_handle(), &alpn_out, &alpn_len);
if (alpn_out == NULL) {
return config.remote_port;
}
auto it = config.ssl.alpn_port_override.find(std::string(alpn_out, alpn_out + alpn_len));
return it == config.ssl.alpn_port_override.end() ? config.remote_port : it->second;
}());
if (valid) {
out_write_buf = req.payload;
if (req.command == TrojanRequest::UDP_ASSOCIATE) {
Expand All @@ -166,7 +178,7 @@ void ServerSession::in_recv(const string &data) {
Log::log_with_endpoint(in_endpoint, "requested connection to " + req.address.address + ':' + to_string(req.address.port), Log::INFO);
}
} else {
Log::log_with_endpoint(in_endpoint, "not trojan request, connecting to " + config.remote_addr + ':' + to_string(config.remote_port), Log::WARN);
Log::log_with_endpoint(in_endpoint, "not trojan request, connecting to " + query_addr + ':' + query_port, Log::WARN);
out_write_buf = data;
}
sent_len += out_write_buf.length();
Expand Down
1 change: 1 addition & 0 deletions tests/LinuxSmokeTest/server.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"cipher_tls13": "",
"prefer_server_cipher": true,
"alpn": [],
"alpn_port_override": {},
"reuse_session": false,
"session_ticket": false,
"session_timeout": 600,
Expand Down