Skip to content

Commit 6f2c2fb

Browse files
committed
Cloud address allow-listing
1 parent b7f6f49 commit 6f2c2fb

File tree

5 files changed

+301
-0
lines changed

5 files changed

+301
-0
lines changed

config/dnsTable.json

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
{
2+
"udp": {
3+
"addresses": [
4+
"3.85.71.8",
5+
"3.210.194.186",
6+
"3.221.51.74",
7+
"3.222.253.60",
8+
"3.223.76.106",
9+
"3.224.151.208",
10+
"3.225.113.205",
11+
"3.227.163.177",
12+
"3.228.117.244",
13+
"3.229.224.193",
14+
"34.194.48.89",
15+
"34.233.0.183",
16+
"52.22.68.60",
17+
"52.70.88.102",
18+
"52.70.247.238",
19+
"54.82.141.176",
20+
"54.86.198.203",
21+
"54.89.110.189",
22+
"54.226.52.22",
23+
"100.25.253.74"
24+
]
25+
},
26+
"tcp": {
27+
"addresses": [
28+
"3.85.71.8",
29+
"3.210.194.186",
30+
"3.222.253.60",
31+
"3.225.113.205",
32+
"3.227.163.177",
33+
"3.228.117.244",
34+
"34.194.48.89",
35+
"54.82.141.176",
36+
"54.86.198.203",
37+
"54.226.52.22",
38+
"54.89.85.128",
39+
"18.215.131.110",
40+
"3.230.94.67",
41+
"3.216.239.14",
42+
"34.195.89.106",
43+
"3.225.178.96",
44+
"3.230.53.201",
45+
"52.1.233.8",
46+
"3.229.48.190",
47+
"54.86.95.155"
48+
]
49+
},
50+
"api": {
51+
"addresses": [
52+
"18.210.55.77",
53+
"23.20.15.229",
54+
"34.234.252.187"
55+
]
56+
},
57+
"tools": {
58+
"addresses": [
59+
"18.232.44.59",
60+
"23.22.157.146",
61+
"35.153.87.190",
62+
"52.84.52.41",
63+
"52.84.52.45",
64+
"52.84.52.61",
65+
"52.84.52.129",
66+
"52.84.129.24",
67+
"52.84.129.37",
68+
"52.84.129.55",
69+
"52.84.129.93",
70+
"104.16.51.111",
71+
"104.16.53.111"
72+
]
73+
}
74+
}

scripts/generateDnsTable.js

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
const dns = require('dns');
4+
5+
6+
const dnsJsonPath = path.join(__dirname, '../config', 'dnsTable.json');
7+
8+
const lookupArray = [
9+
{
10+
"key":"udp",
11+
"hosts":[
12+
"eks-udp-device-service-blue-static.us-east-1.eks-production-gotham.particle.io",
13+
"eks-udp-device-service-green-static.us-east-1.eks-production-gotham.particle.io"
14+
]
15+
},
16+
{
17+
"key":"tcp",
18+
"hosts":[
19+
"eks-tcp-device-service-green-static.us-east-1.eks-production-gotham.particle.io",
20+
"eks-udp-device-service-green-static.us-east-1.eks-production-gotham.particle.io"
21+
]
22+
},
23+
{
24+
"key":"api",
25+
"hosts":[
26+
"api.particle.io"
27+
]
28+
},
29+
{
30+
"key":"tools",
31+
"hosts":[
32+
"build.particle.io",
33+
"console.particle.io",
34+
"docs.particle.io",
35+
"support.particle.io"
36+
]
37+
}
38+
];
39+
40+
// console.log('generating...');
41+
let results = {};
42+
43+
processLookupArray(function() {
44+
fs.writeFileSync(dnsJsonPath, JSON.stringify(results, null, 2));
45+
});
46+
47+
function processLookupArray(completion) {
48+
49+
lookupArray.forEach(function(lookupObj, outerIndex) {
50+
// Create empty keys for the results
51+
if (!results[lookupObj.key]) {
52+
results[lookupObj.key] = {};
53+
}
54+
if (!results[lookupObj.key].addresses) {
55+
results[lookupObj.key].addresses = [];
56+
}
57+
58+
const outerLast = (outerIndex + 1) >= lookupArray.length;
59+
60+
lookupObj.hosts.forEach(function(hostName, innerIndex) {
61+
dns.lookup(hostName, {family:4, all:true}, function(err, addresses) {
62+
const innerLast = (innerIndex + 1) >= lookupObj.hosts.length;
63+
64+
if (err) {
65+
throw err;
66+
}
67+
68+
addresses.forEach(function(obj) {
69+
results[lookupObj.key].addresses.push(obj.address);
70+
});
71+
72+
73+
if (innerLast) {
74+
//console.log('innerLast');
75+
results[lookupObj.key].addresses.sort(ipAddrSort);
76+
// console.log('addresses', results[lookupObj.key].addresses);
77+
78+
// results[lookupObj.key].md = arrayToMd(results[lookupObj.key].addresses);
79+
}
80+
81+
if (outerLast && innerLast) {
82+
//console.log('outerLast && innerLast');
83+
completion();
84+
}
85+
});
86+
});
87+
});
88+
}
89+
90+
function ipAddrSort(a, b) {
91+
const aArray = a.split('.');
92+
const bArray = b.split('.');
93+
94+
if (aArray.length != 4 || bArray.length != 4) {
95+
return a.localeCompare(b);
96+
}
97+
98+
for(let ii = 0; ii < aArray.length; ii++) {
99+
const aInt = parseInt(aArray[ii]);
100+
const bInt = parseInt(bArray[ii]);
101+
102+
if (aInt < bInt) {
103+
return -1;
104+
}
105+
else if (aInt > bInt) {
106+
return +1;
107+
}
108+
}
109+
return 0;
110+
}
111+
112+
/*
113+
function arrayToMd(array) {
114+
var md = '';
115+
116+
md += '| IP address |\n';
117+
md += '| :-------------: |\n';
118+
119+
array.forEach(function(addr) {
120+
md += '| ' + addr + ' '.substr(0, 15 - addr.length) + ' |\n';
121+
});
122+
123+
return md;
124+
}
125+
*/

scripts/metalsmith.js

+7
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ var insertFragment = require('./insert_fragment');
4040
var javascriptDocsPreprocess = require('./javascript_docs_preprocess');
4141
var git = require('git-rev');
4242
var path = require('path');
43+
var fs = require('fs');
4344
var sitemap = require('./sitemap.js');
4445

4546
var handlebars = require('handlebars');
@@ -60,6 +61,8 @@ var generateSearch = process.env.SEARCH_INDEX !== '0';
6061

6162
var noScripts = false;
6263

64+
var dnsTable = JSON.parse(fs.readFileSync(path.join(__dirname, '../config', 'dnsTable.json')));
65+
6366
exports.metalsmith = function () {
6467
function removeEmptyTokens(token) {
6568
if (token.length > 0) {
@@ -121,6 +124,10 @@ exports.metalsmith = function () {
121124
.use(fileMetadata([
122125
{ pattern: 'content/**/*.md', metadata: { assets: '/assets', branch: gitBranch, noScripts: noScripts } }
123126
]))
127+
// Inject the dnsTable into introduction.md so it can be used by the dnsTable helper
128+
.use(fileMetadata([
129+
{ pattern: 'content/tutorials/device-cloud/introduction.md', metadata: { dnsTable: dnsTable } }
130+
]))
124131
.use(msIf(
125132
environment === 'development',
126133
fileMetadata([

src/content/tutorials/device-cloud/introduction.md

+38
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,41 @@ There is no ability for devices to send function calls to other devices; publish
7979
Updating your device firmware and Device OS can be done securely over the Particle cloud connection that's used for the other device cloud features.
8080

8181

82+
## Cloud Services and Firewalls
83+
84+
The IP addresses used by the Particle cloud are subject to change without notice. Use the information here as a last resort if you have a network that restricts traffic and are unable to allow-list traffic by using techniques such as MAC address allow-lists.
85+
86+
### Gen 3 and Gen 2 Cellular
87+
88+
Gen 3 devices (Argon, Boron, B Series, Tracker SoM) and Gen 2 cellular devices (Electron, E Series) all use UDP port 5684, outbound.
89+
90+
While you rarely need to worry about this for cellular devices, for the Argon (Wi-Fi), if you are connecting from a network with a restrictive network firewall, the devices will connect to one of these IP addresses, port 5684, outbound. Like most UDP-based protocols (like DNS), your firewall generally creates a temporary port to allow packets back to the device without creating a permanent firewall port forwarding rule. The amount of time this port will remain active ranges from seconds to hours, and you may need to use [`Particle.keepAlive()`](/reference/device-os/firmware/argon/#particle-keepalive-) to keep the cloud connection active.
91+
92+
{{dnsTable key="udp"}}
93+
94+
### Gen 2 and Gen 1 Wi-Fi
95+
96+
The Photon, P1, and Spark Core connect to TCP Port 5683 (CoAP), outbound.
97+
98+
If you are connecting from a restrictive network that does not allow outbound TCP access on Port 5683, you may need to allow-list these IP addresses or allow access based on the device's MAC address.
99+
100+
{{dnsTable key="tcp"}}
101+
102+
### Cloud API
103+
104+
The devices themselves do not access the Particle Cloud using the API port, but if you are using the Tinker mobile app over Wi-Fi, curl commands, node.js scripts, etc. from a computer on the Wi-Fi or LAN, and you have a restrictive outbound network connection policy, you may need to allow-list **api.particle.io** port 443 (TLS/SSL), outbound, or as a last resort, these IP addresses (subject to change without notice):
105+
106+
{{dnsTable key="api"}}
107+
108+
### Other Services
109+
110+
Other common services includes:
111+
112+
- **console.particle.io** (device management)
113+
- **docs.particle.io** (documentation)
114+
- **build.particle.io** (Web IDE)
115+
- **support.particle.io** (support and knowledge base)
116+
117+
If you are using network with restrictive outbound access policies, you may need to allow-list those DNS names for port 443 (TLS/SSL) outbound, or as a last resort, these IP addresses (subject to change without notice):
118+
119+
{{dnsTable key="tools"}}

templates/helpers/dnsTable.js

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Inserts a table of DNS addresses
2+
// {{dns-table key="udp"}}
3+
// The data is stored in config/dnsTable.json
4+
// The dnsTable.json file is generated or updated by scripts/generateDnsTable.js
5+
var Handlebars = require('handlebars');
6+
7+
var lastCssClass;
8+
9+
module.exports = function(context) {
10+
const key = context.hash.key;
11+
if (!key) {
12+
return '';
13+
}
14+
const columns = context.hash.columns || 5;
15+
16+
// console.log('context', context);
17+
// console.log('context.data.root.dns_table', context.data.root.dns_table);
18+
19+
return generateTable(context.data.root.dnsTable[key].addresses, columns);
20+
};
21+
22+
function generateTable(addresses, columns) {
23+
if (!addresses || addresses.length == 0) {
24+
return '';
25+
}
26+
27+
if (columns > addresses.length) {
28+
columns = addresses.length;
29+
}
30+
let md = '';
31+
let col;
32+
33+
for(col = 0; col < columns; col++) {
34+
md += '| IP Address ';
35+
}
36+
md += '|\n';
37+
38+
for(col = 0; col < columns; col++) {
39+
md += '| :--- ';
40+
}
41+
md += '|\n';
42+
43+
col = 0;
44+
addresses.forEach(function(address) {
45+
md += '| ' + address;
46+
if (++col >= columns) {
47+
col = 0;
48+
md += '|\n';
49+
}
50+
});
51+
if (col != 0) {
52+
md += '|\n';
53+
}
54+
55+
return md;
56+
}
57+

0 commit comments

Comments
 (0)