Skip to content

Commit

Permalink
Allow end user to configure what ports to listen on
Browse files Browse the repository at this point in the history
  • Loading branch information
loki committed Jun 30, 2021
1 parent 8bf4ade commit beb6bdf
Show file tree
Hide file tree
Showing 19 changed files with 149 additions and 69 deletions.
13 changes: 11 additions & 2 deletions assets/sunshine.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# external_ip = 123.456.789.12

# Set the familly of ports used by Sunshine
# port = 47984
# port = 47989

# The private key must be 2048 bits
# pkey = /dir/pkey.pem
Expand Down Expand Up @@ -35,7 +35,16 @@
# lan: Only those in LAN may access /pin
# wan: Anyone may access /pin
#
# origin_pin_allowed = lan
# origin_pin_allowed = pc

# The origin of the remote endpoint address that is not denied for HTTPS Web UI
# Could be any of the following values:
# pc|lan|wan
# pc: Only localhost may access the Web Manager
# lan: Only those in LAN may access the Web Manager
# wan: Anyone may access the Web Manager
#
# origin_web_ui_allowed = lan

# If UPnP is enabled, Sunshine will attempt to open ports for streaming over the internet
# To enable it, uncomment the following line:
Expand Down
37 changes: 29 additions & 8 deletions assets/web/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ <h1 class="my-4">Configuration</h1>
</select>
<div class="form-text">The minimum log level printed to standard out</div>
</div>
<!--Origin PIN Allowed-->
<!--Origin Web UI Allowed-->
<div class="mb-3">
<label for="origin_pin_allowed" class="form-label">Origin PIN Allowed</label>
<select id="origin_pin_allowed" class="form-select" v-model="config.origin_pin_allowed">
<option value="pc">Only localhost may access /pin and Web UI</option>
<option value="lan">Only those in LAN may access /pin and Web UI</option>
<option value="wan">Anyone may access /pin and Web UI</option>
<label for="origin_web_ui_allowed" class="form-label">Origin Web UI Allowed</label>
<select id="origin_web_ui_allowed" class="form-select" v-model="config.origin_web_ui_allowed">
<option value="pc">Only localhost may access Web UI</option>
<option value="lan">Only those in LAN may access Web UI</option>
<option value="wan">Anyone may access Web UI</option>
</select>
<div class="form-text">The origin of the remote endpoint address that is not denied for HTTP method /pin
<div class="form-text">The origin of the remote endpoint address that is not denied access to Web UI
</div>
</div>
<!--UPnP-->
Expand Down Expand Up @@ -238,6 +238,15 @@ <h1 class="my-4">Configuration</h1>
</div>
</div>
<div v-if="currentTab === 'advanced'" class="config-page">
<!--Port familly-->
<div class="mb-3">
<label for="port" class="form-label">Port</label>
<input type="number" min="0" max="65529" class="form-control" id="port" placeholder="47989"
v-model="config.port">
<div class="form-text">
Set the familly of ports used by Sunshine
</div>
</div>
<!--Constant Rate Factor-->
<div class="mb-3">
<label for="crf" class="form-label">Constant Rate Factor</label>
Expand Down Expand Up @@ -341,6 +350,17 @@ <h1 class="my-4">Configuration</h1>
Store Username/Password seperately from Sunshine's state file.
</div>
</div>
<!--Origin PIN Allowed-->
<div class="mb-3">
<label for="origin_pin_allowed" class="form-label">Origin PIN Allowed</label>
<select id="origin_pin_allowed" class="form-select" v-model="config.origin_pin_allowed">
<option value="pc">Only localhost may access /pin</option>
<option value="lan">Only those in LAN may access /pin</option>
<option value="wan">Anyone may access /pin</option>
</select>
<div class="form-text">The origin of the remote endpoint address that is not denied for HTTP method /pin
</div>
</div>
<!--External IP-->
<div class="mb-3">
<label for="external_ip" class="form-label">External IP</label>
Expand Down Expand Up @@ -517,7 +537,8 @@ <h1 class="my-4">Configuration</h1>
//Populate default values if not present in config
this.config.upnp = this.config.upnp || 'disabled';
this.config.min_log_level = this.config.min_log_level || 2;
this.config.origin_pin_allowed = this.config.origin_pin_allowed || "lan";
this.config.origin_pin_allowed = this.config.origin_pin_allowed || "pc";
this.config.origin_web_ui_allowed = this.config.origin_web_manager_allowed || "lan";
this.config.hevc_mode = this.config.hevc_mode || 0;
this.config.encoder = this.config.encoder || '';
this.config.nv_preset = this.config.nv_preset || 'default';
Expand Down
12 changes: 10 additions & 2 deletions sunshine/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@ stream_t stream {
};

nvhttp_t nvhttp {
"lan", // origin_pin
"pc", // origin_pin
"lan", // origin web manager

PRIVATE_KEY_FILE,
CERTIFICATE_FILE,

Expand Down Expand Up @@ -222,7 +224,8 @@ sunshine_t sunshine {
{}, // Password
{}, // Password Salt
SUNSHINE_ASSETS_DIR "/sunshine.conf", // config file
{} // cmd args
{}, // cmd args
47989,
};

bool endline(char ch) {
Expand Down Expand Up @@ -610,6 +613,7 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
string_f(vars, "virtual_sink", audio.virtual_sink);

string_restricted_f(vars, "origin_pin_allowed", nvhttp.origin_pin_allowed, { "pc"sv, "lan"sv, "wan"sv });
string_restricted_f(vars, "origin_web_ui_allowed", nvhttp.origin_web_ui_allowed, { "pc"sv, "lan"sv, "wan"sv });

int to = -1;
int_between_f(vars, "ping_timeout", to, { -1, std::numeric_limits<int>::max() });
Expand Down Expand Up @@ -642,6 +646,10 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
input.key_repeat_delay = std::chrono::milliseconds { to };
}

int port = sunshine.port;
int_f(vars, "port"s, port);
sunshine.port = (std::uint16_t)port;

bool upnp = false;
bool_f(vars, "upnp"s, upnp);

Expand Down
1 change: 1 addition & 0 deletions sunshine/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ struct nvhttp_t {
// Could be any of the following values:
// pc|lan|wan
std::string origin_pin_allowed;
std::string origin_web_ui_allowed;

std::string pkey; // must be 2048 bits
std::string cert; // must be signed with a key of 2048 bits
Expand Down
19 changes: 10 additions & 9 deletions sunshine/confighttp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,9 @@
#include "utility.h"
#include "uuid.h"

namespace confighttp {
using namespace std::literals;
constexpr auto PORT_HTTPS = 47990;

namespace confighttp {
namespace fs = std::filesystem;
namespace pt = boost::property_tree;

Expand Down Expand Up @@ -67,7 +66,7 @@ void print_req(const req_https_t &request) {

void send_unauthorized(resp_https_t response, req_https_t request) {
auto address = request->remote_endpoint_address();
BOOST_LOG(info) << '[' << address << "] -- denied"sv;
BOOST_LOG(info) << "Web UI: ["sv << address << "] -- not authorized"sv;
const SimpleWeb::CaseInsensitiveMultimap headers {
{ "WWW-Authenticate", R"(Basic realm="Sunshine Gamestream Host", charset="UTF-8")" }
};
Expand All @@ -78,8 +77,8 @@ bool authenticate(resp_https_t response, req_https_t request) {
auto address = request->remote_endpoint_address();
auto ip_type = net::from_address(address);

if(ip_type > http::origin_pin_allowed) {
BOOST_LOG(info) << '[' << address << "] -- denied"sv;
if(ip_type > http::origin_web_ui_allowed) {
BOOST_LOG(info) << "Web UI: ["sv << address << "] -- denied"sv;
response->write(SimpleWeb::StatusCode::client_error_forbidden);
return false;
}
Expand Down Expand Up @@ -455,6 +454,8 @@ void savePin(resp_https_t response, req_https_t request) {
void start() {
auto shutdown_event = mail::man->event<bool>(mail::shutdown);

auto port_https = map_port(PORT_HTTPS);

auto ctx = std::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tls);
ctx->use_certificate_chain_file(config::nvhttp.cert);
ctx->use_private_key_file(config::nvhttp.pkey, boost::asio::ssl::context::pem);
Expand All @@ -475,14 +476,14 @@ void start() {
server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp;
server.config.reuse_address = true;
server.config.address = "0.0.0.0"s;
server.config.port = PORT_HTTPS;
server.config.port = port_https;

try {
server.bind();
BOOST_LOG(info) << "Configuration UI available at [https://localhost:"sv << PORT_HTTPS << "]";
BOOST_LOG(info) << "Configuration UI available at [https://localhost:"sv << port_https << "]";
}
catch(boost::system::system_error &err) {
BOOST_LOG(fatal) << "Couldn't bind http server to ports ["sv << PORT_HTTPS << "]: "sv << err.what();
BOOST_LOG(fatal) << "Couldn't bind http server to ports ["sv << port_https << "]: "sv << err.what();

shutdown_event->raise(true);
return;
Expand All @@ -497,7 +498,7 @@ void start() {
return;
}

BOOST_LOG(fatal) << "Couldn't start Configuration HTTP server to ports ["sv << PORT_HTTPS << ", "sv << PORT_HTTPS << "]: "sv << err.what();
BOOST_LOG(fatal) << "Couldn't start Configuration HTTPS server to port ["sv << port_https << "]: "sv << err.what();
shutdown_event->raise(true);
return;
}
Expand Down
3 changes: 2 additions & 1 deletion sunshine/confighttp.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@


namespace confighttp {
constexpr auto PORT_HTTPS = 1;
void start();
}
} // namespace confighttp

#endif //SUNSHINE_CONFIGHTTP_H
7 changes: 5 additions & 2 deletions sunshine/httpcommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,13 @@ bool user_creds_exist(const std::string &file);

std::string unique_id;
net::net_e origin_pin_allowed;
net::net_e origin_web_ui_allowed;

int init() {
bool clean_slate = config::sunshine.flags[config::flag::FRESH_STATE];
origin_pin_allowed = net::from_enum_string(config::nvhttp.origin_pin_allowed);
bool clean_slate = config::sunshine.flags[config::flag::FRESH_STATE];
origin_pin_allowed = net::from_enum_string(config::nvhttp.origin_pin_allowed);
origin_web_ui_allowed = net::from_enum_string(config::nvhttp.origin_web_ui_allowed);

if(clean_slate) {
unique_id = util::uuid_t::generate().string();
auto dir = std::filesystem::temp_directory_path() / "Sushine"sv;
Expand Down
1 change: 1 addition & 0 deletions sunshine/httpcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ int save_user_creds(
int reload_user_creds(const std::string &file);
extern std::string unique_id;
extern net::net_e origin_pin_allowed;
extern net::net_e origin_web_ui_allowed;

} // namespace http
4 changes: 4 additions & 0 deletions sunshine/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,4 +270,8 @@ int write_file(const char *path, const std::string_view &contents) {
out << contents;

return 0;
}

std::uint16_t map_port(int port) {
return (std::uint16_t)((int)config::sunshine.port + port);
}
2 changes: 2 additions & 0 deletions sunshine/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ void print_help(const char *name);
std::string read_file(const char *path);
int write_file(const char *path, const std::string_view &contents);

std::uint16_t map_port(int port);

namespace mail {
#define MAIL(x) \
constexpr auto x = std::string_view { #x }
Expand Down
13 changes: 8 additions & 5 deletions sunshine/nvhttp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ void pin(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response,
auto address = request->remote_endpoint_address();
auto ip_type = net::from_address(address);
if(ip_type > http::origin_pin_allowed) {
BOOST_LOG(info) << '[' << address << "] -- denied"sv;
BOOST_LOG(info) << "/pin: ["sv << address << "] -- denied"sv;

response->write(SimpleWeb::StatusCode::client_error_forbidden);

Expand Down Expand Up @@ -759,6 +759,9 @@ void appasset(resp_https_t response, req_https_t request) {
void start() {
auto shutdown_event = mail::man->event<bool>(mail::shutdown);

auto port_http = map_port(PORT_HTTP);
auto port_https = map_port(PORT_HTTPS);

bool clean_slate = config::sunshine.flags[config::flag::FRESH_STATE];

if(!clean_slate) {
Expand Down Expand Up @@ -836,7 +839,7 @@ void start() {

https_server.config.reuse_address = true;
https_server.config.address = "0.0.0.0"s;
https_server.config.port = PORT_HTTPS;
https_server.config.port = port_https;

http_server.default_resource = not_found<SimpleWeb::HTTP>;
http_server.resource["^/serverinfo$"]["GET"] = serverinfo<SimpleWeb::HTTP>;
Expand All @@ -845,14 +848,14 @@ void start() {

http_server.config.reuse_address = true;
http_server.config.address = "0.0.0.0"s;
http_server.config.port = PORT_HTTP;
http_server.config.port = port_http;

try {
https_server.bind();
http_server.bind();
}
catch(boost::system::system_error &err) {
BOOST_LOG(fatal) << "Couldn't bind http server to ports ["sv << PORT_HTTPS << ", "sv << PORT_HTTP << "]: "sv << err.what();
BOOST_LOG(fatal) << "Couldn't bind http server to ports ["sv << port_http << ", "sv << port_http << "]: "sv << err.what();

shutdown_event->raise(true);
return;
Expand All @@ -868,7 +871,7 @@ void start() {
return;
}

BOOST_LOG(fatal) << "Couldn't start http server to ports ["sv << PORT_HTTPS << ", "sv << PORT_HTTP << "]: "sv << err.what();
BOOST_LOG(fatal) << "Couldn't start http server to ports ["sv << port_https << ", "sv << port_https << "]: "sv << err.what();
shutdown_event->raise(true);
return;
}
Expand Down
4 changes: 2 additions & 2 deletions sunshine/nvhttp.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
#include <string>

namespace nvhttp {
constexpr auto PORT_HTTP = 47989;
constexpr auto PORT_HTTPS = 47984;
constexpr auto PORT_HTTP = 0;
constexpr auto PORT_HTTPS = -5;

void start();
bool pin(std::string pin);
Expand Down
11 changes: 10 additions & 1 deletion sunshine/platform/linux/publish.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,16 @@ void create_services(avahi::Client *c) {
if(avahi::entry_group_is_empty(group)) {
BOOST_LOG(info) << "Adding avahi service "sv << name.get();

ret = avahi::entry_group_add_service(group, avahi::IF_UNSPEC, avahi::PROTO_UNSPEC, avahi::PublishFlags(0), name.get(), SERVICE_TYPE, nullptr, nullptr, nvhttp::PORT_HTTP, nullptr);
ret = avahi::entry_group_add_service(
group,
avahi::IF_UNSPEC, avahi::PROTO_UNSPEC,
avahi::PublishFlags(0),
name.get(),
SERVICE_TYPE,
nullptr, nullptr,
map_port(nvhttp::PORT_HTTP),
nullptr);

if(ret < 0) {
if(ret == avahi::ERR_COLLISION) {
// A service name collision with a local service happened. Let's pick a new name
Expand Down
2 changes: 1 addition & 1 deletion sunshine/platform/windows/publish.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ static int service(bool enable) {

DNS_SERVICE_INSTANCE instance {};
instance.pszInstanceName = name.data();
instance.wPort = nvhttp::PORT_HTTP;
instance.wPort = map_port(nvhttp::PORT_HTTP);
instance.pszHostName = host.data();

DNS_SERVICE_REGISTER_REQUEST req {};
Expand Down
6 changes: 2 additions & 4 deletions sunshine/rtsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ std::string to_string(T &&t) {
return ss.str();
}

constexpr auto RTSP_SETUP_PORT = 48010;

void free_msg(PRTSP_MESSAGE msg) {
freeMessage(msg);

Expand Down Expand Up @@ -505,8 +503,8 @@ void rtpThread() {

server.map("PLAY"sv, &cmd_play);

if(server.bind(RTSP_SETUP_PORT)) {
BOOST_LOG(fatal) << "Couldn't bind RTSP server to port ["sv << RTSP_SETUP_PORT << "], likely another process already bound to the port"sv;
if(server.bind(map_port(RTSP_SETUP_PORT))) {
BOOST_LOG(fatal) << "Couldn't bind RTSP server to port ["sv << map_port(RTSP_SETUP_PORT) << "], likely another process already bound to the port"sv;
shutdown_event->raise(true);

return;
Expand Down
2 changes: 2 additions & 0 deletions sunshine/rtsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "thread_safe.h"

namespace stream {
constexpr auto RTSP_SETUP_PORT = 21;

struct launch_session_t {
crypto::aes_t gcm_key;
crypto::aes_t iv;
Expand Down
Loading

0 comments on commit beb6bdf

Please sign in to comment.