Skip to content

Add support for proxy_protocol in proxy_hosts and streams #4105

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

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
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
3 changes: 2 additions & 1 deletion backend/internal/nginx.js
Original file line number Diff line number Diff line change
@@ -156,7 +156,8 @@ const internalNginx = {
{ssl_forced: host.ssl_forced}, {caching_enabled: host.caching_enabled}, {block_exploits: host.block_exploits},
{allow_websocket_upgrade: host.allow_websocket_upgrade}, {http2_support: host.http2_support},
{hsts_enabled: host.hsts_enabled}, {hsts_subdomains: host.hsts_subdomains}, {access_list: host.access_list},
{certificate: host.certificate}, host.locations[i]);
{certificate: host.certificate}, {proxy_protocol_enabled: host.proxy_protocol_enabled},
{loadbalancer_address: host.loadbalancer_address}, host.locations[i]);

if (locationCopy.forward_host.indexOf('/') > -1) {
const splitted = locationCopy.forward_host.split('/');
56 changes: 56 additions & 0 deletions backend/migrations/20241022221324_proxy_protocol.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
const migrate_name = 'proxy_protocol';
const logger = require('../logger').migrate;

/**
* Migrate
*
* @see http://knexjs.org/#Schema
*
* @param {Object} knex
* @param {Promise} Promise
* @returns {Promise}
*/
exports.up = function (knex/*, Promise*/) {
logger.info('[' + migrate_name + '] Migrating Up...');

return knex.schema.table('proxy_host', function (proxy_host) {
proxy_host.integer('proxy_protocol_enabled').notNull().defaultTo(0);
proxy_host.string('loadbalancer_address').notNull().defaultTo('');
})
.then(() => {
logger.info('[' + migrate_name + '] proxy_host Table altered');

return knex.schema.table('stream', function (stream) {
stream.integer('proxy_protocol_enabled').notNull().defaultTo(0);
stream.string('loadbalancer_address').notNull().defaultTo('');
})
.then(() => {
logger.info('[' + migrate_name + '] stream Table altered');
});
});

};

/**
* Undo Migrate
*
* @param {Object} knex
* @param {Promise} Promise
* @returns {Promise}
*/
exports.down = function (knex/*, Promise*/) {
return knex.schema.table('proxy_host', function (proxy_host) {
proxy_host.dropColumn('proxy_protocol_enabled');
proxy_host.dropColumn('loadbalancer_address');
})
.then(function () {
logger.info('[' + migrate_name + '] proxy_host Table altered');
return knex.schema.table('stream', function (stream) {
stream.dropColumn('proxy_protocol_enabled');
stream.dropColumn('loadbalancer_address');
})
.then(function () {
logger.info('[' + migrate_name + '] stream Table altered');
});
});
};
1 change: 1 addition & 0 deletions backend/models/proxy_host.js
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ const boolFields = [
'enabled',
'hsts_enabled',
'hsts_subdomains',
'proxy_protocol_enabled',
];

class ProxyHost extends Model {
1 change: 1 addition & 0 deletions backend/models/stream.js
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ const boolFields = [
'is_deleted',
'tcp_forwarding',
'udp_forwarding',
'proxy_protocol_enabled',
];

class Stream extends Model {
10 changes: 10 additions & 0 deletions backend/schema/common.json
Original file line number Diff line number Diff line change
@@ -110,6 +110,16 @@
"caching_enabled": {
"description": "Should we cache assets",
"type": "boolean"
},
"proxy_protocol_enabled": {
"description": "Should the proxy_procotol be enabled",
"type": "boolean"
},
"loadbalancer_address": {
"description": "Hostname, IP or CIDR range of the load balancer",
"type": "string",
"minLength": 0,
"maxLength": 255
}
}
}
10 changes: 9 additions & 1 deletion backend/schema/components/proxy-host-object.json
Original file line number Diff line number Diff line change
@@ -23,7 +23,9 @@
"locations",
"hsts_enabled",
"hsts_subdomains",
"certificate"
"certificate",
"proxy_protocol_enabled",
"loadbalancer_address"
],
"additionalProperties": false,
"properties": {
@@ -137,6 +139,12 @@
}
]
},
"proxy_protocol_enabled": {
"$ref": "../common.json#/properties/proxy_protocol_enabled"
},
"loadbalancer_address": {
"$ref": "../common.json#/properties/loadbalancer_address"
},
"owner": {
"$ref": "./user-object.json"
},
8 changes: 7 additions & 1 deletion backend/schema/components/stream-object.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"type": "object",
"description": "Stream object",
"required": ["id", "created_on", "modified_on", "owner_user_id", "incoming_port", "forwarding_host", "forwarding_port", "tcp_forwarding", "udp_forwarding", "enabled", "meta"],
"required": ["id", "created_on", "modified_on", "owner_user_id", "incoming_port", "forwarding_host", "forwarding_port", "tcp_forwarding", "udp_forwarding", "enabled", "meta", "proxy_protocol_enabled", "loadbalancer_address"],
"additionalProperties": false,
"properties": {
"id": {
@@ -55,6 +55,12 @@
},
"meta": {
"type": "object"
},
"proxy_protocol_enabled": {
"$ref": "../common.json#/properties/proxy_protocol_enabled"
},
"loadbalancer_address": {
"$ref": "../common.json#/properties/loadbalancer_address"
}
}
}
4 changes: 3 additions & 1 deletion backend/schema/paths/nginx/proxy-hosts/get.json
Original file line number Diff line number Diff line change
@@ -50,7 +50,9 @@
"enabled": true,
"locations": null,
"hsts_enabled": false,
"hsts_subdomains": false
"hsts_subdomains": false,
"proxy_protocol_enabled": false,
"loadbalancer_address": ""
}
]
}
4 changes: 3 additions & 1 deletion backend/schema/paths/nginx/proxy-hosts/hostID/get.json
Original file line number Diff line number Diff line change
@@ -50,7 +50,9 @@
"enabled": true,
"locations": null,
"hsts_enabled": false,
"hsts_subdomains": false
"hsts_subdomains": false,
"proxy_protocol_enabled": false,
"loadbalancer_address": ""
}
}
},
8 changes: 8 additions & 0 deletions backend/schema/paths/nginx/proxy-hosts/hostID/put.json
Original file line number Diff line number Diff line change
@@ -79,6 +79,12 @@
},
"locations": {
"$ref": "../../../../components/proxy-host-object.json#/properties/locations"
},
"proxy_protocol_enabled": {
"$ref": "../../../../components/proxy-host-object.json#/properties/proxy_protocol_enabled"
},
"loadbalancer_address": {
"$ref": "../../../../components/proxy-host-object.json#/properties/loadbalancer_address"
}
}
}
@@ -116,6 +122,8 @@
"enabled": true,
"hsts_enabled": false,
"hsts_subdomains": false,
"proxy_protocol_enabled": false,
"loadbalancer_address": "",
"owner": {
"id": 1,
"created_on": "2024-10-07T22:43:55.000Z",
8 changes: 8 additions & 0 deletions backend/schema/paths/nginx/proxy-hosts/post.json
Original file line number Diff line number Diff line change
@@ -67,6 +67,12 @@
},
"locations": {
"$ref": "../../../components/proxy-host-object.json#/properties/locations"
},
"proxy_protocol_enabled": {
"$ref": "../../../components/proxy-host-object.json#/properties/proxy_protocol_enabled"
},
"loadbalancer_address": {
"$ref": "../../../components/proxy-host-object.json#/properties/loadbalancer_address"
}
}
}
@@ -101,6 +107,8 @@
"enabled": true,
"hsts_enabled": false,
"hsts_subdomains": false,
"proxy_protocol_enabled": false,
"loadbalancer_address": "",
"certificate": null,
"owner": {
"id": 1,
2 changes: 2 additions & 0 deletions backend/schema/paths/nginx/streams/get.json
Original file line number Diff line number Diff line change
@@ -36,6 +36,8 @@
"forwarding_port": 80,
"tcp_forwarding": true,
"udp_forwarding": false,
"proxy_protocol_enabled": false,
"loadbalancer_address": "",
"meta": {
"nginx_online": true,
"nginx_err": null
8 changes: 8 additions & 0 deletions backend/schema/paths/nginx/streams/post.json
Original file line number Diff line number Diff line change
@@ -32,6 +32,12 @@
"udp_forwarding": {
"$ref": "../../../components/stream-object.json#/properties/udp_forwarding"
},
"proxy_protocol_enabled": {
"$ref": "../../../components/stream-object.json#/properties/proxy_protocol_enabled"
},
"loadbalancer_address": {
"$ref": "../../../components/stream-object.json#/properties/loadbalancer_address"
},
"meta": {
"$ref": "../../../components/stream-object.json#/properties/meta"
}
@@ -57,6 +63,8 @@
"forwarding_port": 80,
"tcp_forwarding": true,
"udp_forwarding": false,
"proxy_protocol_enabled": false,
"loadbalancer_address": "",
"meta": {
"nginx_online": true,
"nginx_err": null
2 changes: 2 additions & 0 deletions backend/schema/paths/nginx/streams/streamID/get.json
Original file line number Diff line number Diff line change
@@ -36,6 +36,8 @@
"forwarding_port": 80,
"tcp_forwarding": true,
"udp_forwarding": false,
"proxy_protocol_enabled": false,
"loadbalancer_address": "",
"meta": {
"nginx_online": true,
"nginx_err": null
8 changes: 8 additions & 0 deletions backend/schema/paths/nginx/streams/streamID/put.json
Original file line number Diff line number Diff line change
@@ -79,6 +79,12 @@
},
"locations": {
"$ref": "../../../../components/proxy-host-object.json#/properties/locations"
},
"proxy_protocol_enabled": {
"$ref": "../../../../components/proxy-host-object.json#/properties/proxy_protocol_enabled"
},
"loadbalancer_address": {
"$ref": "../../../../components/proxy-host-object.json#/properties/loadbalancer_address"
}
}
}
@@ -116,6 +122,8 @@
"enabled": true,
"hsts_enabled": false,
"hsts_subdomains": false,
"proxy_protocol_enabled": false,
"loadbalancer_address": "",
"owner": {
"id": 1,
"created_on": "2024-10-07T22:43:55.000Z",
34 changes: 24 additions & 10 deletions backend/templates/_listen.conf
Original file line number Diff line number Diff line change
@@ -1,20 +1,34 @@
listen 80;

{% if proxy_protocol_enabled == 1 or proxy_protocol_enabled == true -%}
{% assign port_number_http = "88" -%}
{% assign port_number_https = "444" -%}
{% assign listen_extra_args = "proxy_protocol" -%}
{% else -%}
{% assign port_number_http = "80" -%}
{% assign port_number_https = "443" -%}
{% assign listen_extra_args = "" -%}
{% endif -%}

listen {{ port_number_http }} {{ listen_extra_args }};
{% if ipv6 -%}
listen [::]:80;
listen [::]:{{ port_number_http }} {{ listen_extra_args }};
{% else -%}
#listen [::]:80;
{% endif %}
#listen [::]:{{ port_number_http }} {{ listen_extra_args }};
{% endif -%}

{% if certificate -%}
listen 443 ssl;
{% capture listen_extra_args_https %}ssl {{ listen_extra_args }}{% endcapture -%}
listen {{ port_number_https }} {{ listen_extra_args_https }};
{% if ipv6 -%}
listen [::]:443 ssl;
listen [::]:{{ port_number_https }} {{ listen_extra_args_https }};
{% else -%}
#listen [::]:443;
{% endif %}
{% endif %}
#listen [::]:{{ port_number_https }} {{ listen_extra_args_https }};
{% endif -%}
{% endif -%}

server_name {{ domain_names | join: " " }};
{% if http2_support == 1 or http2_support == true %}
http2 on;
{% else -%}
http2 off;
{% endif %}
{% endif %}
6 changes: 6 additions & 0 deletions backend/templates/_proxy_protocol.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{% if proxy_protocol_enabled == 1 or proxy_protocol_enabled == true %}
{% if loadbalancer_address != '' %}
set_real_ip_from {{ loadbalancer_address }};
real_ip_header proxy_protocol;
{% endif %}
{% endif %}
1 change: 1 addition & 0 deletions backend/templates/proxy_host.conf
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@ server {
{% include "_exploits.conf" %}
{% include "_hsts.conf" %}
{% include "_forced_ssl.conf" %}
{% include "_proxy_protocol.conf" %}

{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
proxy_set_header Upgrade $http_upgrade;
19 changes: 13 additions & 6 deletions backend/templates/stream.conf
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
# ------------------------------------------------------------
# {{ incoming_port }} TCP: {{ tcp_forwarding }} UDP: {{ udp_forwarding }}
# ------------------------------------------------------------
{% if proxy_protocol_enabled == 1 or proxy_protocol_enabled == true -%}
{% capture listen_extra_args %}proxy_protocol{% endcapture -%}
{% endif -%}

{% if enabled %}
{% if tcp_forwarding == 1 or tcp_forwarding == true -%}
server {
listen {{ incoming_port }};
listen {{ incoming_port }} {{ listen_extra_args }};
{% if ipv6 -%}
listen [::]:{{ incoming_port }};
listen [::]:{{ incoming_port }} {{ listen_extra_args }};
{% else -%}
#listen [::]:{{ incoming_port }};
#listen [::]:{{ incoming_port }}{{ listen_extra_args }};
{% endif %}

proxy_pass {{ forwarding_host }}:{{ forwarding_port }};

{% include '_proxy_protocol.conf' %}

# Custom
include /data/nginx/custom/server_stream[.]conf;
include /data/nginx/custom/server_stream_tcp[.]conf;
}
{% endif %}
{% if udp_forwarding == 1 or udp_forwarding == true %}
{% # Proxy Protocol is not supported for UDP %}
{% assign listen_extra_args = "" %}
server {
listen {{ incoming_port }} udp;
listen {{ incoming_port }} udp {{ listen_extra_args }};
{% if ipv6 -%}
listen [::]:{{ incoming_port }} udp;
listen [::]:{{ incoming_port }} udp {{ listen_extra_args }};
{% else -%}
#listen [::]:{{ incoming_port }} udp;
#listen [::]:{{ incoming_port }} udp {{ listen_extra_args }};
{% endif %}
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};

3 changes: 2 additions & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -35,7 +35,8 @@ RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
COPY docker/scripts/install-s6 /tmp/install-s6
RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6

EXPOSE 80 81 443
# http admin_ui http_proxy_protocol https https_proxy_protocol
EXPOSE 80 81 88 443 444

COPY backend /app
COPY frontend/dist /app/frontend
3 changes: 2 additions & 1 deletion docker/dev/Dockerfile
Original file line number Diff line number Diff line change
@@ -35,5 +35,6 @@ RUN rm -f /etc/nginx/conf.d/production.conf \
COPY --from=pebbleca /test/certs/pebble.minica.pem /etc/ssl/certs/pebble.minica.pem
COPY --from=testca /home/step/certs/root_ca.crt /etc/ssl/certs/NginxProxyManager.crt

EXPOSE 80 81 443
# http admin_ui http_proxy_protocol https https_proxy_protocol
EXPOSE 80 81 88 443 444
ENTRYPOINT [ "/init" ]
Loading