Damien Garrido
2015-Mar-22 03:10 UTC
[Icecast-dev] exposed-port option for Icecast behind reverse proxy
Hello, I didn't want to have to choose between Icecast running on port 80 and all my Apache virtual hosts, running also on port 80, on my sole external IP address. I didn't want either to open port 8000 on my firewall because I wanted all users being able to reach Icecast even the ones behind enterprise firewalls. So I managed to run Apache 2.2 listening on port 80 and Icecast 2.3.2 listening on port 8000 on the same host. I added a new virtual host radio.domain.com (listening on port 80) which is routing the Icecast traffic to/from the local Icecast server (listening on port 8000): <VirtualHost *:80> ServerName radio.domain.com ServerAdmin hostmaster at domain.com ProxyPreserveHost On ProxyPass / localhost:8000 ProxyPassReverse / localhost:8000 </VirtualHost> I was then able to connect audio clients like VLC/Winamp to Icecast mount points using addresses like radio.domain.com/my_stream. However, when connecting to the Icecast virtual host radio.domain.com web page, the m3u and the xspf files where still exposing the URL radio.domain.com:8000/my_stream with that annoying port 8000. Then people downloading those files weren't able to connect to the Icecast server because they were trying to connect on the wrong port. The same was occuring with the YP updates ondir.xiph.org. I then downloaded the Icecast 2.3.2 source code, and modified it to add a new option: <exposed-port>80</exposed-port> If this option is present in the Icecast configuration file, then m3u/xspf files as well as YP updates will use that port number. The below patch is for Icecast version 2.3.2: diff --git a/src/cfgfile.c b/src/cfgfile.c index 5eac93d..42d917f 100644 --- a/src/cfgfile.c +++ b/src/cfgfile.c @@ -436,6 +436,10 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node, configuration->mimetypes_fn = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); } else if (xmlStrcmp (node->name, XMLSTR("listen-socket")) == 0) { _parse_listen_socket(doc, node->xmlChildrenNode, configuration); + } else if (xmlStrcmp (node->name, XMLSTR("exposed-port")) == 0) { + tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + configuration->exposed_port = atoi(tmp); + if (tmp) xmlFree(tmp); } else if (xmlStrcmp (node->name, XMLSTR("port")) == 0) { tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); configuration->port = atoi(tmp); @@ -801,6 +805,12 @@ static void _parse_listen_socket(xmlDocPtr doc, xmlNodePtr node, listener->port = atoi(tmp); if(tmp) xmlFree(tmp); } + else if (xmlStrcmp (node->name, XMLSTR("exposed-port")) == 0) { + tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if(configuration->exposed_port == 0) + configuration->exposed_port = atoi(tmp); + if(tmp) xmlFree(tmp); + } else if (xmlStrcmp (node->name, XMLSTR("ssl")) == 0) { tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); listener->ssl = atoi(tmp); diff --git a/src/cfgfile.h b/src/cfgfile.h index fa5aa69..44a5bea 100644 --- a/src/cfgfile.h +++ b/src/cfgfile.h @@ -138,6 +138,7 @@ typedef struct ice_config_tag char *hostname; int port; + int exposed_port; char *mimetypes_fn; listener_t *listen_sock; diff --git a/src/fserve.c b/src/fserve.c index 724aaaf..3f50472 100644 --- a/src/fserve.c +++ b/src/fserve.c @@ -443,7 +443,7 @@ int fserve_client_create (client_t *httpclient, const char *path) "HTTP/1.0 200 OK\r\n" "Content-Type: audio/x-mpegurl\r\n\r\n" "http://%s:%d%s\r\n", - config->hostname, config->port, + config->hostname, ( config->exposed_port ? config->exposed_port : config->port ), sourceuri ); config_release_config(); diff --git a/src/icecast b/src/icecast new file mode 100755 index 0000000..7e4f612 Binary files /dev/null and b/src/icecast differ diff --git a/src/source.c b/src/source.c index 02bfc74..b838799 100644 --- a/src/source.c +++ b/src/source.c @@ -579,7 +579,7 @@ static void source_init (source_t *source) listenurl = malloc (listen_url_size); memset (listenurl, '00', listen_url_size); snprintf (listenurl, listen_url_size, "http://%s:%d%s", - config->hostname, config->port, source->mount); + config->hostname, ( config->exposed_port ? config->exposed_port : config->port ), source->mount); config_release_config(); str = httpp_getvar(source->parser, "ice-audio-info"); diff --git a/src/yp.c b/src/yp.c index 4470d47..e3acb5f 100644 --- a/src/yp.c +++ b/src/yp.c @@ -584,12 +584,12 @@ static ypdata_t *create_yp_entry (const char *mount) if (url == NULL) break; config = config_get_config(); - ret = snprintf (url, len, "http://%s:%d%s", config->hostname, config->port, mount); + ret = snprintf (url, len, "http://%s:%d%s", config->hostname, ( config->exposed_port ? config->exposed_port : config->port ), mount); if (ret >= (signed)len) { s = realloc (url, ++ret); if (s) url = s; - snprintf (url, ret, "http://%s:%d%s", config->hostname, config->port, mount); + snprintf (url, ret, "http://%s:%d%s", config->hostname, ( config->exposed_port ? config->exposed_port : config->port ), mount); } mountproxy = config_find_mount (config, mount); -- Damien Garrido Dev (C/C++/PHP/Perl/Python) Ops (on Debian/Ubuntu) -------------- next part -------------- An HTML attachment was scrubbed... URL: lists.xiph.org/pipermail/icecast-dev/attachments/20150322/02198f67/attachment.htm
Micheil Smith
2015-Mar-22 04:08 UTC
[Icecast-dev] exposed-port option for Icecast behind reverse proxy
The way I achieved this at NTS Radio was to edit the xslt views for the website part. Although, if a feature such as this were to land, I think it'd make sense to have it as an exposed-url option, rather than a exposed-port option. ? Micheil On 22 Mar 2015, at 03:10, Damien Garrido <damien.garrido.work at gmail.com> wrote:> Hello, > > I didn't want to have to choose between Icecast running on port 80 and all my Apache virtual hosts, running also on port 80, on my sole external IP address. > > I didn't want either to open port 8000 on my firewall because I wanted all users being able to reach Icecast even the ones behind enterprise firewalls. > > So I managed to run Apache 2.2 listening on port 80 and Icecast 2.3.2 listening on port 8000 on the same host. > > I added a new virtual host radio.domain.com (listening on port 80) which is routing the Icecast traffic to/from the local Icecast server (listening on port 8000): > > <VirtualHost *:80> > ServerName radio.domain.com > ServerAdmin hostmaster at domain.com > ProxyPreserveHost On > ProxyPass / localhost:8000 > ProxyPassReverse / localhost:8000 > </VirtualHost> > I was then able to connect audio clients like VLC/Winamp to Icecast mount points using addresses like radio.domain.com/my_stream. > > However, when connecting to the Icecast virtual host radio.domain.com web page, the m3u and the xspf files where still exposing the URL radio.domain.com:8000/my_stream with that annoying port 8000. Then people downloading those files weren't able to connect to the Icecast server because they were trying to connect on the wrong port. The same was occuring with the YP updates ondir.xiph.org. > > I then downloaded the Icecast 2.3.2 source code, and modified it to add a new option: > > <exposed-port>80</exposed-port> > If this option is present in the Icecast configuration file, then m3u/xspf files as well as YP updates will use that port number. > > The below patch is for Icecast version 2.3.2: > > diff --git a/src/cfgfile.c b/src/cfgfile.c > index 5eac93d..42d917f 100644 > --- a/src/cfgfile.c > +++ b/src/cfgfile.c > @@ -436,6 +436,10 @@ static void _parse_root(xmlDocPtr doc, xmlNodePtr node, > configuration->mimetypes_fn = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); > } else if (xmlStrcmp (node->name, XMLSTR("listen-socket")) == 0) { > _parse_listen_socket(doc, node->xmlChildrenNode, configuration); > + } else if (xmlStrcmp (node->name, XMLSTR("exposed-port")) == 0) { > + tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); > + configuration->exposed_port = atoi(tmp); > + if (tmp) xmlFree(tmp); > } else if (xmlStrcmp (node->name, XMLSTR("port")) == 0) { > tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); > configuration->port = atoi(tmp); > @@ -801,6 +805,12 @@ static void _parse_listen_socket(xmlDocPtr doc, xmlNodePtr node, > listener->port = atoi(tmp); > if(tmp) xmlFree(tmp); > } > + else if (xmlStrcmp (node->name, XMLSTR("exposed-port")) == 0) { > + tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); > + if(configuration->exposed_port == 0) > + configuration->exposed_port = atoi(tmp); > + if(tmp) xmlFree(tmp); > + } > else if (xmlStrcmp (node->name, XMLSTR("ssl")) == 0) { > tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); > listener->ssl = atoi(tmp); > diff --git a/src/cfgfile.h b/src/cfgfile.h > index fa5aa69..44a5bea 100644 > --- a/src/cfgfile.h > +++ b/src/cfgfile.h > @@ -138,6 +138,7 @@ typedef struct ice_config_tag > > char *hostname; > int port; > + int exposed_port; > char *mimetypes_fn; > > listener_t *listen_sock; > diff --git a/src/fserve.c b/src/fserve.c > index 724aaaf..3f50472 100644 > --- a/src/fserve.c > +++ b/src/fserve.c > @@ -443,7 +443,7 @@ int fserve_client_create (client_t *httpclient, const char *path) > "HTTP/1.0 200 OK\r\n" > "Content-Type: audio/x-mpegurl\r\n\r\n" > "http://%s:%d%s\r\n", > - config->hostname, config->port, > + config->hostname, ( config->exposed_port ? config->exposed_port : config->port ), > sourceuri > ); > config_release_config(); > diff --git a/src/icecast b/src/icecast > new file mode 100755 > index 0000000..7e4f612 > Binary files /dev/null and b/src/icecast differ > diff --git a/src/source.c b/src/source.c > index 02bfc74..b838799 100644 > --- a/src/source.c > +++ b/src/source.c > @@ -579,7 +579,7 @@ static void source_init (source_t *source) > listenurl = malloc (listen_url_size); > memset (listenurl, '00', listen_url_size); > snprintf (listenurl, listen_url_size, "http://%s:%d%s", > - config->hostname, config->port, source->mount); > + config->hostname, ( config->exposed_port ? config->exposed_port : config->port ), source->mount); > config_release_config(); > > str = httpp_getvar(source->parser, "ice-audio-info"); > diff --git a/src/yp.c b/src/yp.c > index 4470d47..e3acb5f 100644 > --- a/src/yp.c > +++ b/src/yp.c > @@ -584,12 +584,12 @@ static ypdata_t *create_yp_entry (const char *mount) > if (url == NULL) > break; > config = config_get_config(); > - ret = snprintf (url, len, "http://%s:%d%s", config->hostname, config->port, mount); > + ret = snprintf (url, len, "http://%s:%d%s", config->hostname, ( config->exposed_port ? config->exposed_port : config->port ), mount); > if (ret >= (signed)len) > { > s = realloc (url, ++ret); > if (s) url = s; > - snprintf (url, ret, "http://%s:%d%s", config->hostname, config->port, mount); > + snprintf (url, ret, "http://%s:%d%s", config->hostname, ( config->exposed_port ? config->exposed_port : config->port ), mount); > } > > mountproxy = config_find_mount (config, mount); > > -- > Damien Garrido > Dev (C/C++/PHP/Perl/Python) > Ops (on Debian/Ubuntu) > _______________________________________________ > Icecast-dev mailing list > Icecast-dev at xiph.org > lists.xiph.org/mailman/listinfo/icecast-dev-------------- next part -------------- An HTML attachment was scrubbed... URL: lists.xiph.org/pipermail/icecast-dev/attachments/20150322/a62410d6/attachment-0001.htm
"Thomas B. Rücker"
2015-Mar-22 05:59 UTC
[Icecast-dev] exposed-port option for Icecast behind reverse proxy
Hi, On 03/22/2015 03:10 AM, Damien Garrido wrote:> Hello, > > I didn't want to have to choose between Icecast running on port 80 and > all my Apache virtual hosts, running also on port 80, on my sole > external IP address. > > I didn't want either to open port 8000 on my firewall because I wanted > all users being able to reach Icecast even the ones behind enterprise > firewalls. > > So I managed to run Apache 2.2 listening on port 80 and Icecast 2.3.2 > listening on port 8000 on the same host. >I hope you're experienced with reverse proxies and the implications. We generally don't recommend this as users tend to underestimate the impact and also the Icecast code base is not prepared for being behind a reverse proxy. In addition to what you see, e.g. your access.log and some of the admin pages will be rather useless, listing ::1 or 127.0.0.1 as the origin address of all connections. We are considering how to make Icecast more suitable for reverse proxy setups. So your input is certainly welcome.> I added a new virtual host radio.domain.com > <radio.domain.com> (listening on port 80) which is routing the > Icecast traffic to/from the local Icecast server (listening on port 8000): > > |<VirtualHost *:80> > ServerName radio.domain.com <radio.domain.com> > ServerAdmin hostmaster at domain.com <mailto:hostmaster at domain.com> > ProxyPreserveHost On > ProxyPass / localhost:8000 > ProxyPassReverse / localhost:8000 > </VirtualHost> > | > > I was then able to connect audio clients like VLC/Winamp to Icecast > mount points using addresses like |radio.domain.com/my_stream|. > > However, when connecting to the Icecast virtual > host |radio.domain.com/| web page, the m3u and the xspf files > where still exposing the > URL |radio.domain.com:8000/my_stream| with that annoying port > 8000. Then people downloading those files weren't able to connect to > the Icecast server because they were trying to connect on the wrong > port. The same was occuring with the YP updates ondir.xiph.org > <dir.xiph.org>. > > I then downloaded the Icecast 2.3.2 source code, and modified it to > add a new option: > > |<exposed-port>80</exposed-port>|The latest Icecast stable version is 2.4.1, we strongly recommend using that due to previous security issues and tons of bugfixes. Development patches are preferably against git head. Details how to check out can be found here: wiki.xiph.org/Icecast/Git_workflow> If this option is present in the Icecast configuration file, then > m3u/xspf files as well as YP updates will use that port number. > > The below patch is for Icecast version 2.3.2: ><snip value="removed HTML 'patch'"> Please send patches as attachments, HTML mails tend to malform them. Also preferably use plain text emails on mailing lists. Cheers Thomas