Sikau

AWS · Day 4 · about 45 min

Project: A secure VPC

Security group rules with CIDRs and group references.

Who can talk to the database?

Your servers live in a VPC, a private network. Security groups are firewalls on each instance: inbound rules allow a protocol and port range from a CIDR block — or from *members of another group*. The classic layout: the internet reaches only the load balancer, the load balancer reaches the web servers, and only web servers reach the database.

Evaluating rules

const ipToInt = (ip) => ip.split(".").reduce((n, part) => n * 256 + Number(part), 0);

function inCidr(ip, cidr) {
  const [base, bits] = cidr.split("/");
  const size = 2 ** (32 - Number(bits));
  return Math.floor(ipToInt(ip) / size) === Math.floor(ipToInt(base) / size);
}
function ruleAllows(rule, { protocol, port, sourceIp, sourceGroups = [] }) {
  if (rule.protocol !== "-1" && rule.protocol !== protocol) return false; // "-1" means every protocol
  if (rule.protocol !== "-1" && (port < rule.fromPort || port > rule.toPort)) return false;
  if (rule.cidr) return inCidr(sourceIp, rule.cidr);
  return sourceGroups.includes(rule.sourceGroup); // traffic from members of another group
}

function canReach(instances, groups, from, to, { protocol = "tcp", port }) {
  const src = instances[from];
  const dst = instances[to];
  const packet = { protocol, port, sourceIp: src.ip, sourceGroups: src.groups };
  return dst.groups.some((g) => groups[g].inbound.some((rule) => ruleAllows(rule, packet)));
}
const groups = {
  "sg-lb": { inbound: [{ protocol: "tcp", fromPort: 443, toPort: 443, cidr: "0.0.0.0/0" }] },
  "sg-web": { inbound: [{ protocol: "tcp", fromPort: 8080, toPort: 8080, sourceGroup: "sg-lb" }, { protocol: "tcp", fromPort: 22, toPort: 22, cidr: "10.0.9.0/24" }] },
  "sg-db": { inbound: [{ protocol: "tcp", fromPort: 5432, toPort: 5432, sourceGroup: "sg-web" }] },
  "sg-admin": { inbound: [{ protocol: "-1", cidr: "10.0.9.0/24" }] },
};
const instances = {
  internet: { ip: "203.0.113.7", groups: [] },
  lb: { ip: "10.0.1.10", groups: ["sg-lb"] },
  web: { ip: "10.0.2.20", groups: ["sg-web"] },
  db: { ip: "10.0.3.30", groups: ["sg-db", "sg-admin"] },
  bastion: { ip: "10.0.9.5", groups: [] },
};

The rest of this lesson

  • Public and private subnetsexplain
  • Rules that reference groupsexplain
  • Request pathorder
  • Reachable or not?match
  • Check reachabilitywrite code
  • Badge quizquiz
  • What you builtrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 8 lessons of AWS