Skip to content

Commit b57d1e5

Browse files
committed
Added Stream forwarding support
1 parent d2130a2 commit b57d1e5

File tree

15 files changed

+264
-38
lines changed

15 files changed

+264
-38
lines changed

manager/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nginx-proxy-manager",
3-
"version": "1.0.1",
3+
"version": "1.1.0",
44
"description": "Nginx proxt with built in Web based management",
55
"main": "src/backend/index.js",
66
"dependencies": {

manager/src/backend/internal/host.js

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,31 @@ const internalHost = {
4444
*/
4545
create: payload => {
4646
return new Promise((resolve, reject) => {
47-
// Enforce lowercase hostnames
48-
payload.hostname = payload.hostname.toLowerCase();
47+
let existing_host = false;
4948

50-
// 1. Check that the hostname doesn't already exist
51-
let existing_host = db.hosts.findOne({hostname: payload.hostname});
49+
if (payload.type === 'stream') {
50+
// Check that the incoming port doesn't already exist
51+
existing_host = db.hosts.findOne({incoming_port: payload.incoming_port});
52+
53+
if (payload.incoming_port === 80 || payload.incoming_port === 81 || payload.incoming_port === 443) {
54+
reject(new error.ConfigurationError('Port ' + payload.incoming_port + ' is reserved'));
55+
return;
56+
}
57+
58+
} else {
59+
payload.hostname = payload.hostname.toLowerCase();
60+
61+
// Check that the hostname doesn't already exist
62+
existing_host = db.hosts.findOne({hostname: payload.hostname});
63+
}
5264

5365
if (existing_host) {
5466
reject(new error.ValidationError('Hostname already exists'));
5567
} else {
56-
// 2. Add host to db
68+
// Add host to db
5769
let host = db.hosts.save(payload);
5870

59-
// 3. Fire the config generation for this host
71+
// Fire the config generation for this host
6072
internalHost.configure(host, true)
6173
.then((/*result*/) => {
6274
resolve(host);
@@ -98,10 +110,16 @@ const internalHost = {
98110
}
99111

100112
// Check that the hostname doesn't already exist
101-
let other_host = db.hosts.findOne({hostname: payload.hostname});
113+
let other_host = false;
114+
115+
if (typeof payload.incoming_port !== 'undefined') {
116+
other_host = db.hosts.findOne({incoming_port: payload.incoming_port});
117+
} else {
118+
other_host = db.hosts.findOne({hostname: payload.hostname});
119+
}
102120

103121
if (other_host && other_host._id !== id) {
104-
reject(new error.ValidationError('Hostname already exists'));
122+
reject(new error.ValidationError((other_host.type === 'stream' ? 'Source Stream Port' : 'Hostname') + ' already exists'));
105123
} else {
106124
// 2. Update host
107125
db.hosts.update({_id: id}, payload, {multi: false, upsert: false});
@@ -126,17 +144,22 @@ const internalHost = {
126144
return data;
127145
})
128146
.then(data => {
129-
if (
130-
(data.original.ssl && !data.updated.ssl) || // ssl was enabled and is now disabled
131-
(data.original.ssl && data.original.hostname !== data.updated.hostname) // hostname was changed for a previously ssl-enabled host
132-
) {
133-
// SSL was turned off or hostname for ssl has changed so we should remove certs for the original
134-
return internalSsl.deleteCerts(data.original)
135-
.then(() => {
136-
db.hosts.update({_id: data.updated._id}, {ssl_expires: 0}, {multi: false, upsert: false});
137-
data.updated.ssl_expires = 0;
138-
return data;
139-
});
147+
if (data.updated.type !== 'stream') {
148+
if (
149+
(data.original.ssl && !data.updated.ssl) || // ssl was enabled and is now disabled
150+
(data.original.ssl && data.original.hostname !== data.updated.hostname) // hostname was changed for a previously ssl-enabled host
151+
) {
152+
// SSL was turned off or hostname for ssl has changed so we should remove certs for the original
153+
return internalSsl.deleteCerts(data.original)
154+
.then(() => {
155+
db.hosts.update({_id: data.updated._id}, {ssl_expires: 0}, {
156+
multi: false,
157+
upsert: false
158+
});
159+
data.updated.ssl_expires = 0;
160+
return data;
161+
});
162+
}
140163
}
141164

142165
return data;

manager/src/backend/internal/nginx.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ const internalNginx = {
3232
* @returns {String}
3333
*/
3434
getConfigName: host => {
35+
if (host.type === 'stream') {
36+
return '/config/nginx/stream/' + host.incoming_port + '.conf';
37+
}
38+
3539
return '/config/nginx/' + host.hostname + '.conf';
3640
},
3741

manager/src/backend/schema/endpoints/hosts.json

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
},
1313
"type": {
1414
"type": "string",
15-
"pattern": "^(proxy|redirection|404)$"
15+
"pattern": "^(proxy|redirection|404|stream)$"
1616
},
1717
"hostname": {
1818
"$ref": "../definitions.json#/definitions/hostname"
@@ -59,6 +59,17 @@
5959
"access_list": {
6060
"type": "object",
6161
"readonly": true
62+
},
63+
"incoming_port": {
64+
"type": "integer",
65+
"minumum": 1,
66+
"maxiumum": 65535
67+
},
68+
"protocols": {
69+
"type": "array",
70+
"items": {
71+
"type": "string"
72+
}
6273
}
6374
},
6475
"links": [
@@ -86,8 +97,7 @@
8697
"schema": {
8798
"type": "object",
8899
"required": [
89-
"type",
90-
"hostname"
100+
"type"
91101
],
92102
"properties": {
93103
"type": {
@@ -125,6 +135,12 @@
125135
},
126136
"access_list_id": {
127137
"$ref": "#/definitions/access_list_id"
138+
},
139+
"incoming_port": {
140+
"$ref": "#/definitions/incoming_port"
141+
},
142+
"protocols": {
143+
"$ref": "#/definitions/protocols"
128144
}
129145
}
130146
},
@@ -181,6 +197,12 @@
181197
},
182198
"access_list_id": {
183199
"$ref": "#/definitions/access_list_id"
200+
},
201+
"incoming_port": {
202+
"$ref": "#/definitions/incoming_port"
203+
},
204+
"protocols": {
205+
"$ref": "#/definitions/protocols"
184206
}
185207
}
186208
},
@@ -247,6 +269,12 @@
247269
},
248270
"advanced": {
249271
"$ref": "#/definitions/advanced"
272+
},
273+
"incoming_port": {
274+
"$ref": "#/definitions/incoming_port"
275+
},
276+
"protocols": {
277+
"$ref": "#/definitions/protocols"
250278
}
251279
}
252280
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# <%- incoming_port %> - <%- protocols.join(',').toUpperCase() %>
2+
<%
3+
protocols.forEach(function (protocol) {
4+
%>
5+
server {
6+
listen <%- incoming_port %> <%- protocol === 'tcp' ? '' : protocol %>;
7+
proxy_pass <%- forward_server %>:<%- forward_port %>;
8+
}
9+
<%
10+
});
11+
%>

manager/src/frontend/js/app/controller.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,17 @@ module.exports = {
8686
});
8787
},
8888

89+
/**
90+
* Show Stream Host Form
91+
*
92+
* @param model
93+
*/
94+
showStreamHostForm: function (model) {
95+
require(['./main', './host/stream_form'], function (App, View) {
96+
App.UI.showModalDialog(new View({model: model}));
97+
});
98+
},
99+
89100
/**
90101
* Show Delete Host Confirmation
91102
*

manager/src/frontend/js/app/dashboard/main.ejs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<table class="table table-condensed table-striped">
22
<thead>
3-
<th>Hostname</th>
3+
<th>Source</th>
44
<th>Destination</th>
55
<th>SSL</th>
66
<th>Access List</th>
@@ -13,6 +13,7 @@
1313
<li><a href="#" class="new-proxy">Proxy Host</a></li>
1414
<li><a href="#" class="new-redirection">Redirection Host</a></li>
1515
<li><a href="#" class="new-404">404 Host</a></li>
16+
<li><a href="#" class="new-stream">Stream Host</a></li>
1617
</ul>
1718
</div>
1819
</th>

manager/src/frontend/js/app/dashboard/main.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ module.exports = Mn.View.extend({
2828
ui: {
2929
new_proxy: 'th .new-proxy',
3030
new_redirection: 'th .new-redirection',
31-
new_404: 'th .new-404'
31+
new_404: 'th .new-404',
32+
new_stream: 'th .new-stream'
3233
},
3334

3435
events: {
@@ -45,6 +46,11 @@ module.exports = Mn.View.extend({
4546
'click @ui.new_404': function (e) {
4647
e.preventDefault();
4748
Controller.show404HostForm(new HostModel.Model);
49+
},
50+
51+
'click @ui.new_stream': function (e) {
52+
e.preventDefault();
53+
Controller.showStreamHostForm(new HostModel.Model);
4854
}
4955
},
5056

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
<td><a href="<%- ssl ? 'https' : 'http' %>://<%- hostname %>" target="_blank"><%- hostname %></a></td>
1+
<td>
2+
<% if (type === 'stream') { %>
3+
<%- incoming_port %>
4+
<%- protocols.join(', ').toUpperCase() %>
5+
<% } else { %>
6+
<a href="<%- ssl ? 'https' : 'http' %>://<%- hostname %>" target="_blank"><%- hostname %></a>
7+
<% } %>
8+
</td>
29
<td>
310
<span class="monospace">
4-
<% if (type === 'proxy') { %>
11+
<% if (type === 'proxy' || type === 'stream') { %>
512
<%- forward_server %>:<%- forward_port %>
613
<% } else if (type === 'redirection') { %>
714
<%- forward_host %>
@@ -11,27 +18,35 @@
1118
</span>
1219
</td>
1320
<td>
14-
<% if (ssl && force_ssl) { %>
15-
Forced
16-
<% } else if (ssl) { %>
17-
Enabled
21+
<% if (type === 'stream') { %>
22+
-
1823
<% } else { %>
19-
No
24+
<% if (ssl && force_ssl) { %>
25+
Forced
26+
<% } else if (ssl) { %>
27+
Enabled
28+
<% } else { %>
29+
No
30+
<% } %>
2031
<% } %>
2132
</td>
2233
<td>
23-
<% if (access_list) { %>
24-
<a href="#" class="access_list"><%- access_list.name %></a>
34+
<% if (type === 'stream') { %>
35+
-
2536
<% } else { %>
26-
<em>None</em>
37+
<% if (access_list) { %>
38+
<a href="#" class="access_list"><%- access_list.name %></a>
39+
<% } else { %>
40+
<em>None</em>
41+
<% } %>
2742
<% } %>
2843
</td>
2944
<td class="text-right">
3045
<% if (ssl) { %>
3146
<button type="button" class="btn btn-default btn-xs renew" title="Renew SSL"><i class="fa fa-shield" aria-hidden="true"></i></button>
3247
<% } %>
3348
<button type="button" class="btn btn-default btn-xs reconfigure" title="Reconfigure Nginx"><i class="fa fa-refresh" aria-hidden="true"></i></button>
34-
<button type="button" class="btn btn-default btn-xs advanced" title="Advanced Configuration"><i class="fa fa-code" aria-hidden="true"></i></button>
49+
<button type="button" class="btn btn-default btn-xs advanced" title="Advanced Configuration"<%- type === 'stream' ? ' disabled' : '' %>><i class="fa fa-code" aria-hidden="true"></i></button>
3550
<button type="button" class="btn btn-warning btn-xs edit" title="Edit"><i class="fa fa-pencil" aria-hidden="true"></i></button>
3651
<button type="button" class="btn btn-danger btn-xs delete" title="Delete"><i class="fa fa-times" aria-hidden="true"></i></button>
3752
</td>

manager/src/frontend/js/app/dashboard/row.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ module.exports = Mn.View.extend({
3232
case '404':
3333
Controller.show404HostForm(this.model);
3434
break;
35+
case 'stream':
36+
Controller.showStreamHostForm(this.model);
37+
break;
3538
}
3639
},
3740

0 commit comments

Comments
 (0)