Configure prevention pairing over non-private network

This commit is contained in:
loki
2019-12-27 16:04:18 +01:00
parent b054adae06
commit b3ae81cb3a
8 changed files with 195 additions and 11 deletions

View File

@@ -79,6 +79,8 @@ set(SUNSHINE_TARGET_FILES
sunshine/platform/common.h sunshine/platform/common.h
sunshine/process.cpp sunshine/process.cpp
sunshine/process.h sunshine/process.h
sunshine/network.cpp
sunshine/network.h
sunshine/move_by_copy.h sunshine/move_by_copy.h
sunshine/task_pool.h sunshine/task_pool.h
sunshine/thread_pool.h sunshine/thread_pool.h

View File

@@ -10,6 +10,15 @@
# The name displayed by Moonlight # The name displayed by Moonlight
# sunshine_name = sunshine # sunshine_name = sunshine
# The origin of the remote endpoint address that is not denied for HTTP method /pin
# Could be any of the following values:
# pc|lan|wan
# pc: Only localhost may access /pin
# lan: Only those in LAN may access /pin
# wan: Anyone may access /pin
#
# origin_pin_allowed = lan
# Pretty self-explanatory # Pretty self-explanatory
unique_id = 03904e64-51da-4fb3-9afd-a9f7ff70fea4 unique_id = 03904e64-51da-4fb3-9afd-a9f7ff70fea4
@@ -25,7 +34,7 @@ ping_timeout = 2000
# How much error correcting packets must be send for every video max_b_frames # How much error correcting packets must be send for every video max_b_frames
# This is just some random number, don't know the optimal value # This is just some random number, don't know the optimal value
# The higher fec_percentage, the lower space for the actual data to send per frame there is # The higher fec_percentage, the lower space for the actual data to send per frame there is
fec_percentage = 1 fec_percentage = 10
# The back/select button on the controller # The back/select button on the controller
@@ -39,7 +48,7 @@ fec_percentage = 1
# FFmpeg software encoding parameters # FFmpeg software encoding parameters
# Honestly, I have no idea what the optimal values would be. # Honestly, I have no idea what the optimal values would be.
# Play around with this :) # Play around with this :)
max_b_frames = 16 max_b_frames = 4
gop_size = 24 gop_size = 24
# Constant Rate Factor. Between 1 and 52. It allows QP to go up during motion and down with still image, resulting in constant perceived quality # Constant Rate Factor. Between 1 and 52. It allows QP to go up during motion and down with still image, resulting in constant perceived quality

View File

@@ -36,12 +36,13 @@ stream_t stream {
}; };
nvhttp_t nvhttp { nvhttp_t nvhttp {
"lan", // origin_pin
PRIVATE_KEY_FILE, PRIVATE_KEY_FILE,
CERTIFICATE_FILE, CERTIFICATE_FILE,
"sunshine", // sunshine_name "sunshine"s, // sunshine_name,
"03904e64-51da-4fb3-9afd-a9f7ff70fea4", // unique_id "03904e64-51da-4fb3-9afd-a9f7ff70fea4"s, // unique_id
"devices.json" // file_devices "devices.json"s // file_devices
}; };
input_t input { input_t input {
@@ -102,6 +103,32 @@ void string_f(std::unordered_map<std::string, std::string> &vars, const std::str
input = std::move(it->second); input = std::move(it->second);
} }
void string_restricted_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::string &input, const std::vector<std::string_view> &allowed_vals) {
std::string temp;
string_f(vars, name, temp);
for(auto &allowed_val : allowed_vals) {
if(temp == allowed_val) {
input = std::move(temp);
return;
}
}
}
void int_restricted_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input, const std::vector<std::string_view> &allowed_vals) {
std::string temp;
string_f(vars, name, temp);
for(int x = 0; x < allowed_vals.size(); ++x) {
auto &allowed_val = allowed_vals[x];
if(temp == allowed_val) {
input = x;
return;
}
}
}
void int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input) { void int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input) {
auto it = vars.find(name); auto it = vars.find(name);
@@ -142,6 +169,10 @@ void parse_file(const char *file) {
string_f(vars, "file_devices", nvhttp.file_devices); string_f(vars, "file_devices", nvhttp.file_devices);
string_f(vars, "external_ip", nvhttp.external_ip); string_f(vars, "external_ip", nvhttp.external_ip);
string_restricted_f(vars, "origin_pin_allowed", nvhttp.origin_pin_allowed, {
"pc"sv, "lan"sv, "wan"sv
});
int to = -1; int to = -1;
int_f(vars, "ping_timeout", to); int_f(vars, "ping_timeout", to);
if(to > 0) { if(to > 0) {

View File

@@ -28,6 +28,10 @@ struct stream_t {
}; };
struct nvhttp_t { struct nvhttp_t {
// Could be any of the following values:
// pc|lan|wan
std::string origin_pin_allowed;
std::string pkey; // must be 2048 bits std::string pkey; // must be 2048 bits
std::string cert; // must be signed with a key of 2048 bits std::string cert; // must be signed with a key of 2048 bits

96
sunshine/network.cpp Normal file
View File

@@ -0,0 +1,96 @@
//
// Created by loki on 12/27/19.
//
#include <algorithm>
#include "network.h"
#include "utility.h"
namespace net {
using namespace std::literals;
// In the format "xxx.xxx.xxx.xxx/x"
std::pair<std::uint32_t, std::uint32_t> ip_block(const std::string_view &ip);
std::vector<std::pair<std::uint32_t, std::uint32_t>> pc_ips {
ip_block("127.0.0.1/32"sv)
};
std::vector<std::tuple<std::uint32_t, std::uint32_t>> lan_ips {
ip_block("192.168.0.0/16"sv),
ip_block("172.16.0.0/12"),
ip_block("10.0.0.0/8"sv)
};
std::uint32_t ip(const std::string_view &ip_str) {
auto begin = std::begin(ip_str);
auto end = std::end(ip_str);
auto temp_end = std::find(begin, end, '.');
std::uint32_t ip = 0;
auto shift = 24;
while(temp_end != end) {
ip += (util::from_chars(begin, temp_end) << shift);
shift -= 8;
begin = temp_end + 1;
temp_end = std::find(begin, end, '.');
}
ip += util::from_chars(begin, end);
return ip;
}
// In the format "xxx.xxx.xxx.xxx/x"
std::pair<std::uint32_t, std::uint32_t> ip_block(const std::string_view &ip_str) {
auto begin = std::begin(ip_str);
auto end = std::find(begin, std::end(ip_str), '/');
auto addr = ip({ begin, (std::size_t)(end - begin) });
auto bits = 32 - util::from_chars(end + 1, std::end(ip_str));
return { addr, addr + ((1 << bits) - 1) };
}
net_e from_enum_string(const std::string_view &view) {
if(view == "wan") {
return WAN;
}
if(view == "lan") {
return LAN;
}
return PC;
}
net_e from_address(const std::string_view &view) {
auto addr = ip(view);
for(auto [ip_low, ip_high] : pc_ips) {
if(addr >= ip_low && addr <= ip_high) {
return PC;
}
}
for(auto [ip_low, ip_high] : lan_ips) {
if(addr >= ip_low && addr <= ip_high) {
return LAN;
}
}
return WAN;
}
std::string_view to_enum_string(net_e net) {
switch(net) {
case PC:
return "pc"sv;
case LAN:
return "lan"sv;
case WAN:
return "wan"sv;
}
// avoid warning
return "wan"sv;
}
}

22
sunshine/network.h Normal file
View File

@@ -0,0 +1,22 @@
//
// Created by loki on 12/27/19.
//
#ifndef SUNSHINE_NETWORK_H
#define SUNSHINE_NETWORK_H
#include <tuple>
namespace net {
enum net_e : int {
PC,
LAN,
WAN
};
net_e from_enum_string(const std::string_view &view);
std::string_view to_enum_string(net_e net);
net_e from_address(const std::string_view &view);
}
#endif //SUNSHINE_NETWORK_H

View File

@@ -22,6 +22,7 @@
#include "nvhttp.h" #include "nvhttp.h"
#include "platform/common.h" #include "platform/common.h"
#include "process.h" #include "process.h"
#include "network.h"
namespace nvhttp { namespace nvhttp {
@@ -37,7 +38,6 @@ namespace pt = boost::property_tree;
std::string read_file(const char *path); std::string read_file(const char *path);
std::string local_ip;
using https_server_t = SimpleWeb::Server<SimpleWeb::HTTPS>; using https_server_t = SimpleWeb::Server<SimpleWeb::HTTPS>;
using http_server_t = SimpleWeb::Server<SimpleWeb::HTTP>; using http_server_t = SimpleWeb::Server<SimpleWeb::HTTP>;
@@ -88,6 +88,8 @@ enum class op_e {
}; };
std::int64_t current_appid { -1 }; std::int64_t current_appid { -1 };
std::string local_ip;
net::net_e origin_pin_allowed;
void save_devices() { void save_devices() {
pt::ptree root; pt::ptree root;
@@ -374,6 +376,16 @@ template<class T>
void pin(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) { void pin(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) {
print_req<T>(request); print_req<T>(request);
auto address = request->remote_endpoint_address();
auto ip_type = net::from_address(address);
if(ip_type > origin_pin_allowed) {
std::cout << '[' << address << "] -- denied"sv << std::endl;
response->write(SimpleWeb::StatusCode::client_error_forbidden);
return;
}
pt::ptree tree; pt::ptree tree;
auto &sess = std::begin(map_id_sess)->second; auto &sess = std::begin(map_id_sess)->second;
@@ -384,16 +396,22 @@ void pin(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response,
pt::write_xml(data, tree); pt::write_xml(data, tree);
auto &async_response = sess.async_insert_pin.response; auto &async_response = sess.async_insert_pin.response;
if(async_response.left()) { if(async_response.has_left() && async_response.left()) {
async_response.left()->write(data.str()); async_response.left()->write(data.str());
} }
else { else if(async_response.has_right() && async_response.right()){
async_response.right()->write(data.str()); async_response.right()->write(data.str());
} }
else {
response->write(SimpleWeb::StatusCode::client_error_im_a_teapot);
return;
}
// reset async_response
async_response = std::decay_t<decltype(async_response.left())>(); async_response = std::decay_t<decltype(async_response.left())>();
// response to the current request // response to the current request
response->write(""s); response->write(SimpleWeb::StatusCode::success_ok);
} }
template<class T> template<class T>
@@ -631,6 +649,8 @@ void appasset(resp_https_t response, req_https_t request) {
void start() { void start() {
local_ip = platf::get_local_ip(); local_ip = platf::get_local_ip();
origin_pin_allowed = net::from_enum_string(config::nvhttp.origin_pin_allowed);
if(local_ip.empty()) { if(local_ip.empty()) {
std::cout << "Error: Could not determine the local ip-address"sv << std::endl; std::cout << "Error: Could not determine the local ip-address"sv << std::endl;