Free up port 53
It's all very complicated. Approach 1: Simple move unbound to not listen on 0.0.0.0 and only the internal ones. However, docker has no way to bind only to the "public" interface. Approach 2: Move the internal unbound to some other port. This required a PR for haraka - https://github.com/haraka/Haraka/pull/2863 . This works and we use systemd-resolved by default. However, it turns out systemd-resolved with hog the lo and thus docker cannot bind again to port 53. Approach 3: Get rid of systemd-resolved and try to put the dns server list in /etc/resolv.conf. This is surprisingly hard because the DNS listing can come from DHCP or netplan or wherever. We can hardcode some public DNS servers but this seems not a good idea for privacy. Approach 4: So maybe we don't move the unbound away to different port after all. However, all the work for approach 2 is done and it's quite nice that the default resolver is used with the default dns server of the network (probably a caching server + also maybe has some home network firewalled dns). So, the final solution is to bind to the make docker bind to the IP explicity. It's unclear what will happen if the IP changes, maybe it needs a restart.
This commit is contained in:
1
CHANGES
1
CHANGES
@@ -2137,4 +2137,5 @@
|
||||
* Apps can optionally request an authwall to be installed in front of them
|
||||
* mailbox can now owned by a group
|
||||
* linode: enable dns provider in setup view
|
||||
* dns: apps can now use the dns port
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ debconf-set-selections <<< 'mysql-server mysql-server/root_password password pas
|
||||
debconf-set-selections <<< 'mysql-server mysql-server/root_password_again password password'
|
||||
|
||||
# this enables automatic security upgrades (https://help.ubuntu.com/community/AutomaticSecurityUpdates)
|
||||
# resolvconf is needed for unbound to work property after disabling systemd-resolved in 18.04
|
||||
gpg_package=$([[ "${ubuntu_version}" == "16.04" ]] && echo "gnupg" || echo "gpg")
|
||||
mysql_package=$([[ "${ubuntu_version}" == "20.04" ]] && echo "mysql-server-8.0" || echo "mysql-server-5.7")
|
||||
apt-get -y install \
|
||||
@@ -48,7 +47,6 @@ apt-get -y install \
|
||||
$mysql_package \
|
||||
openssh-server \
|
||||
pwgen \
|
||||
resolvconf \
|
||||
swaks \
|
||||
tzdata \
|
||||
unattended-upgrades \
|
||||
@@ -145,21 +143,7 @@ fi
|
||||
systemctl stop bind9 || true
|
||||
systemctl disable bind9 || true
|
||||
|
||||
# on ovh images dnsmasq seems to run by default
|
||||
systemctl stop dnsmasq || true
|
||||
systemctl disable dnsmasq || true
|
||||
|
||||
# on ssdnodes postfix seems to run by default
|
||||
systemctl stop postfix || true
|
||||
systemctl disable postfix || true
|
||||
|
||||
# on ubuntu 18.04, this is the default. this requires resolvconf for DNS to work further after the disable
|
||||
systemctl stop systemd-resolved || true
|
||||
systemctl disable systemd-resolved || true
|
||||
|
||||
# ubuntu's default config for unbound does not work if ipv6 is disabled. this config is overwritten in start.sh
|
||||
# we need unbound to work as this is required for installer.sh to do any DNS requests
|
||||
ip6=$([[ -s /proc/net/if_inet6 ]] && echo "yes" || echo "no")
|
||||
echo -e "server:\n\tinterface: 127.0.0.1\n\tdo-ip6: ${ip6}" > /etc/unbound/unbound.conf.d/cloudron-network.conf
|
||||
systemctl restart unbound
|
||||
|
||||
|
||||
6
package-lock.json
generated
6
package-lock.json
generated
@@ -743,9 +743,9 @@
|
||||
}
|
||||
},
|
||||
"cloudron-manifestformat": {
|
||||
"version": "5.8.1",
|
||||
"resolved": "https://registry.npmjs.org/cloudron-manifestformat/-/cloudron-manifestformat-5.8.1.tgz",
|
||||
"integrity": "sha512-9UZQwh8ohOlY5t+PuUP10EQTD5iLJiKaYCuncjNh3xgqVlEIPRkmhwXdNZmx9WS2RbFft3sSaE7U89y6GYjeUQ==",
|
||||
"version": "5.8.3",
|
||||
"resolved": "https://registry.npmjs.org/cloudron-manifestformat/-/cloudron-manifestformat-5.8.3.tgz",
|
||||
"integrity": "sha512-8lrxUZlNUjReOOgPwFsARA2sVtHvmHFBUXFJ29Ss/sH89hMJneR2FihR6NTbi57UAE5AG+DH+ftHfaW+riWSgg==",
|
||||
"requires": {
|
||||
"cron": "^1.8.2",
|
||||
"java-packagename-regex": "^1.0.0",
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"aws-sdk": "^2.759.0",
|
||||
"basic-auth": "^2.0.1",
|
||||
"body-parser": "^1.19.0",
|
||||
"cloudron-manifestformat": "^5.8.1",
|
||||
"cloudron-manifestformat": "^5.8.3",
|
||||
"connect": "^3.7.0",
|
||||
"connect-lastmile": "^2.0.0",
|
||||
"connect-timeout": "^1.9.0",
|
||||
|
||||
@@ -134,6 +134,11 @@ if ! id "${user}" 2>/dev/null; then
|
||||
useradd "${user}" -m
|
||||
fi
|
||||
|
||||
if which resolvconf; then
|
||||
echo "==> installer: uninstall resolvconf"
|
||||
apt remove -y resolvconf
|
||||
fi
|
||||
|
||||
if [[ "${is_update}" == "yes" ]]; then
|
||||
echo "==> installer: stop box service for update"
|
||||
${box_src_dir}/setup/stop.sh
|
||||
|
||||
@@ -106,8 +106,8 @@ systemctl disable cloudron.target || true
|
||||
rm -f /etc/systemd/system/cloudron.target
|
||||
[[ "${ubuntu_version}" == "16.04" ]] && sed -e 's/MemoryMax/MemoryLimit/g' -i /etc/systemd/system/box.service
|
||||
systemctl daemon-reload
|
||||
systemctl enable unbound
|
||||
systemctl enable cloudron-syslog
|
||||
systemctl enable --now unbound
|
||||
systemctl enable --now cloudron-syslog
|
||||
systemctl enable box
|
||||
systemctl enable cloudron-firewall
|
||||
|
||||
@@ -117,8 +117,7 @@ systemctl restart cloudron-firewall
|
||||
# For logrotate
|
||||
systemctl enable --now cron
|
||||
|
||||
# ensure unbound runs
|
||||
systemctl restart unbound
|
||||
systemctl enable --now systemd-resolved
|
||||
|
||||
# ensure cloudron-syslog runs
|
||||
systemctl restart cloudron-syslog
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
server:
|
||||
interface: 0.0.0.0
|
||||
port: 533
|
||||
interface: 127.0.0.1
|
||||
interface: 172.18.0.1
|
||||
do-ip6: no
|
||||
access-control: 127.0.0.1 allow
|
||||
access-control: 172.18.0.1/16 allow
|
||||
|
||||
@@ -1200,8 +1200,6 @@ function startMysql(existingInfra, callback) {
|
||||
--log-opt syslog-address=udp://127.0.0.1:2514 \
|
||||
--log-opt syslog-format=rfc5424 \
|
||||
--log-opt tag=mysql \
|
||||
--dns 172.18.0.1 \
|
||||
--dns-search=. \
|
||||
-e CLOUDRON_MYSQL_TOKEN=${cloudronToken} \
|
||||
-e CLOUDRON_MYSQL_ROOT_HOST=172.18.0.1 \
|
||||
-e CLOUDRON_MYSQL_ROOT_PASSWORD=${rootPassword} \
|
||||
@@ -1419,8 +1417,6 @@ function startPostgresql(existingInfra, callback) {
|
||||
--log-opt syslog-address=udp://127.0.0.1:2514 \
|
||||
--log-opt syslog-format=rfc5424 \
|
||||
--log-opt tag=postgresql \
|
||||
--dns 172.18.0.1 \
|
||||
--dns-search=. \
|
||||
-e CLOUDRON_POSTGRESQL_ROOT_PASSWORD="${rootPassword}" \
|
||||
-e CLOUDRON_POSTGRESQL_TOKEN="${cloudronToken}" \
|
||||
-v "${dataDir}/postgresql:/var/lib/postgresql" \
|
||||
@@ -1599,8 +1595,6 @@ function startTurn(existingInfra, callback) {
|
||||
--log-opt tag=turn \
|
||||
-m ${memoryLimit}m \
|
||||
--memory-swap ${memoryLimit * 2}m \
|
||||
--dns 172.18.0.1 \
|
||||
--dns-search=. \
|
||||
-e CLOUDRON_TURN_SECRET="${turnSecret}" \
|
||||
-e CLOUDRON_REALM="${realm}" \
|
||||
--label isCloudronManaged=true \
|
||||
@@ -1639,8 +1633,6 @@ function startMongodb(existingInfra, callback) {
|
||||
--log-opt syslog-address=udp://127.0.0.1:2514 \
|
||||
--log-opt syslog-format=rfc5424 \
|
||||
--log-opt tag=mongodb \
|
||||
--dns 172.18.0.1 \
|
||||
--dns-search=. \
|
||||
-e CLOUDRON_MONGODB_ROOT_PASSWORD="${rootPassword}" \
|
||||
-e CLOUDRON_MONGODB_TOKEN="${cloudronToken}" \
|
||||
-v "${dataDir}/mongodb:/var/lib/mongodb" \
|
||||
@@ -1867,8 +1859,6 @@ function setupRedis(app, options, callback) {
|
||||
--log-opt tag="${redisName}" \
|
||||
-m ${memoryLimit/2} \
|
||||
--memory-swap ${memoryLimit} \
|
||||
--dns 172.18.0.1 \
|
||||
--dns-search=. \
|
||||
-e CLOUDRON_REDIS_PASSWORD="${redisPassword}" \
|
||||
-e CLOUDRON_REDIS_TOKEN="${redisServiceToken}" \
|
||||
-v "${paths.PLATFORM_DATA_DIR}/redis/${app.id}:/var/lib/redis" \
|
||||
|
||||
@@ -155,7 +155,6 @@ function validatePortBindings(portBindings, manifest) {
|
||||
const RESERVED_PORTS = [
|
||||
22, /* ssh */
|
||||
25, /* smtp */
|
||||
53, /* dns */
|
||||
80, /* http */
|
||||
143, /* imap */
|
||||
202, /* alternate ssh */
|
||||
@@ -192,7 +191,7 @@ function validatePortBindings(portBindings, manifest) {
|
||||
if (!Number.isInteger(hostPort)) return new BoxError(BoxError.BAD_FIELD, `${hostPort} is not an integer`, { field: 'portBindings', portName: portName });
|
||||
if (RESERVED_PORTS.indexOf(hostPort) !== -1) return new BoxError(BoxError.BAD_FIELD, `Port ${hostPort} is reserved.`, { field: 'portBindings', portName: portName });
|
||||
if (RESERVED_PORT_RANGES.find(range => (hostPort >= range[0] && hostPort <= range[1]))) return new BoxError(BoxError.BAD_FIELD, `Port ${hostPort} is reserved.`, { field: 'portBindings', portName: portName });
|
||||
if (hostPort <= 1023 || hostPort > 65535) return new BoxError(BoxError.BAD_FIELD, `${hostPort} is not in permitted range`, { field: 'portBindings', portName: portName });
|
||||
if (hostPort !== 53 && (hostPort <= 1023 || hostPort > 65535)) return new BoxError(BoxError.BAD_FIELD, `${hostPort} is not in permitted range`, { field: 'portBindings', portName: portName }); // dns 53 is special and adblocker apps can use them
|
||||
}
|
||||
|
||||
// it is OK if there is no 1-1 mapping between values in manifest.tcpPorts and portBindings. missing values implies
|
||||
|
||||
@@ -28,6 +28,7 @@ exports = module.exports = {
|
||||
INTERNAL_SMTP_PORT: 2525, // this value comes from the mail container
|
||||
AUTHWALL_PORT: 3001,
|
||||
LDAP_PORT: 3002,
|
||||
DNS_PORT: 533,
|
||||
DOCKER_PROXY_PORT: 3003,
|
||||
|
||||
NGINX_DEFAULT_CONFIG_FILE_NAME: 'default.conf',
|
||||
|
||||
@@ -39,6 +39,7 @@ var addons = require('./addons.js'),
|
||||
constants = require('./constants.js'),
|
||||
debug = require('debug')('box:docker'),
|
||||
Docker = require('dockerode'),
|
||||
os = require('os'),
|
||||
path = require('path'),
|
||||
settings = require('./settings.js'),
|
||||
shell = require('./shell.js'),
|
||||
@@ -208,6 +209,18 @@ function getBinds(app, callback) {
|
||||
});
|
||||
}
|
||||
|
||||
function getLowerUpIp() { // see getifaddrs and IFF_LOWER_UP and netdevice
|
||||
const ni = os.networkInterfaces(); // { lo: [], eth0: [] }
|
||||
for (const iname of Object.keys(ni)) {
|
||||
if (iname === 'lo') continue;
|
||||
for (const address of ni[iname]) {
|
||||
if (!address.internal && address.family === 'IPv4') return address.address;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function createSubcontainer(app, name, cmd, options, callback) {
|
||||
assert.strictEqual(typeof app, 'object');
|
||||
assert.strictEqual(typeof name, 'string');
|
||||
@@ -249,7 +262,8 @@ function createSubcontainer(app, name, cmd, options, callback) {
|
||||
exposedPorts[`${containerPort}/${portType}`] = {};
|
||||
portEnv.push(`${portName}=${hostPort}`);
|
||||
|
||||
dockerPortBindings[`${containerPort}/${portType}`] = [ { HostIp: '0.0.0.0', HostPort: hostPort + '' } ];
|
||||
const hostIp = hostPort === 53 ? getLowerUpIp() : '0.0.0.0'; // port 53 is special because it is possibly taken by systemd-resolved
|
||||
dockerPortBindings[`${containerPort}/${portType}`] = [ { HostIp: hostIp, HostPort: hostPort + '' } ];
|
||||
}
|
||||
|
||||
let appEnv = [];
|
||||
|
||||
@@ -29,8 +29,6 @@ function startGraphite(existingInfra, callback) {
|
||||
--log-opt tag=graphite \
|
||||
-m 150m \
|
||||
--memory-swap 150m \
|
||||
--dns 172.18.0.1 \
|
||||
--dns-search=. \
|
||||
-p 127.0.0.1:2003:2003 \
|
||||
-p 127.0.0.1:2004:2004 \
|
||||
-p 127.0.0.1:8417:8000 \
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
exports = module.exports = {
|
||||
// a version change recreates all containers with latest docker config
|
||||
'version': '48.17.1',
|
||||
'version': '48.18.0',
|
||||
|
||||
'baseImages': [
|
||||
{ repo: 'cloudron/base', tag: 'cloudron/base:2.0.0@sha256:f9fea80513aa7c92fe2e7bf3978b54c8ac5222f47a9a32a7f8833edf0eb5a4f4' }
|
||||
@@ -20,7 +20,7 @@ exports = module.exports = {
|
||||
'postgresql': { repo: 'cloudron/postgresql', tag: 'cloudron/postgresql:3.3.0@sha256:ad73bff9825c96260a8fd54d1e4b398c48b4b8787c5130e910693de4e96c584e' },
|
||||
'mongodb': { repo: 'cloudron/mongodb', tag: 'cloudron/mongodb:3.0.0@sha256:59e50b1f55e433ffdf6d678f8c658812b4119f631db8325572a52ee40d3bc562' },
|
||||
'redis': { repo: 'cloudron/redis', tag: 'cloudron/redis:2.3.0@sha256:0e31ec817e235b1814c04af97b1e7cf0053384aca2569570ce92bef0d95e94d2' },
|
||||
'mail': { repo: 'cloudron/mail', tag: 'cloudron/mail:2.10.0@sha256:3aff92bfc85d6ca3cc6fc381c8a89625d2af95cc55ed2db692ef4e483e600372' },
|
||||
'mail': { repo: 'cloudron/mail', tag: 'cloudron/mail:3.0.0@sha256:014b651f42384c915677acb8b323d1cd18fe5194fb0e6874020a1e1bbad0bbef' },
|
||||
'graphite': { repo: 'cloudron/graphite', tag: 'cloudron/graphite:2.3.0@sha256:b7bc1ca4f4d0603a01369a689129aa273a938ce195fe43d00d42f4f2d5212f50' },
|
||||
'sftp': { repo: 'cloudron/sftp', tag: 'cloudron/sftp:3.0.0@sha256:5b249db20ee559de2e3b669526763538cf1ec554966b51accdb7056b9be8fc0f' }
|
||||
}
|
||||
|
||||
@@ -666,10 +666,9 @@ function configureMail(mailFqdn, mailDomain, callback) {
|
||||
--log-opt tag=mail \
|
||||
-m ${memoryLimit}m \
|
||||
--memory-swap ${memoryLimit * 2}m \
|
||||
--dns 172.18.0.1 \
|
||||
--dns-search=. \
|
||||
-e CLOUDRON_MAIL_TOKEN="${cloudronToken}" \
|
||||
-e CLOUDRON_RELAY_TOKEN="${relayToken}" \
|
||||
-e CLOUDRON_FTS="true" \
|
||||
-v "${paths.MAIL_DATA_DIR}:/app/data" \
|
||||
-v "${paths.PLATFORM_DATA_DIR}/addons/mail:/etc/mail" \
|
||||
${ports} \
|
||||
|
||||
@@ -9,7 +9,7 @@ var assert = require('assert'),
|
||||
dns = require('dns'),
|
||||
_ = require('underscore');
|
||||
|
||||
const DEFAULT_OPTIONS = { server: '127.0.0.1', timeout: 5000 }; // unbound runs on 127.0.0.1
|
||||
const DEFAULT_OPTIONS = { server: `127.0.0.1:${constants.DNS_PORT}`, timeout: 5000 }; // unbound runs on 127.0.0.1
|
||||
|
||||
// a note on TXT records. It doesn't have quotes ("") at the DNS level. Those quotes
|
||||
// are added for DNS server software to enclose spaces. Such quotes may also be returned
|
||||
|
||||
@@ -105,8 +105,6 @@ function rebuild(callback) {
|
||||
--log-opt tag=sftp \
|
||||
-m ${memoryLimit}m \
|
||||
--memory-swap ${memoryLimit * 2}m \
|
||||
--dns 172.18.0.1 \
|
||||
--dns-search=. \
|
||||
-p 222:22 \
|
||||
${mounts} \
|
||||
-e CLOUDRON_SFTP_TOKEN="${cloudronToken}" \
|
||||
|
||||
Reference in New Issue
Block a user