Laboratorijska vežba – Modul 25 – Projektovanje i izrada VPC mreže
Cilj vežbe
- Deo 1 (svi polaznici, besplatno): isprojektovati VPC za firmu (adresni plan u dve zone dostupnosti, tabele ruta, security group-e i network ACL) i proveriti adresni plan Python skriptom.
- Deo 2 (opciono, AWS): u stvarnom AWS nalogu napraviti VPC sa javnim i privatnim subnetom, internet gateway-em, tabelom ruta, security group-om, network ACL-om i jednim veb serverom. Zatim dijagnostikovati dva tipična kvara i obrisati sve resurse.
Napomena o troškovima (Deo 2): VPC, subneti, tabele ruta, internet gateway, security group-e i network ACL-ovi se ne naplaćuju. Naplaćuju se EC2 instanca i javna IPv4 adresa, po satu. U okviru besplatnih pogodnosti novih naloga to je obično besplatno, a i bez njih vežba od 1–2 sata košta svega nekoliko centi. Uslovi se menjaju, pa ih proverite na stranici AWS Free Tier. Ne pravite NAT gateway ni load balancer, osim u dodatnom izazovu, uz tamo opisane mere. Korak 14 (brisanje resursa) je obavezan.
Potrebno predznanje
- Kompletna teorija ovog modula (Teme 1–15).
- Subnetting i VLSM (Modul 5), rutiranje (Modul 11), stateful/stateless filtriranje (Modul 16), osnove Python-a (Modul 24).
Potrebni programi
- Deo 1: Python 3 (Ubuntu Server VM iz Modula 18 ili bilo koji računar) i editor teksta.
- Deo 2: veb pregledač i AWS nalog. AWS CloudShell (komandna linija u pregledaču, sa već podešenim AWS CLI-jem) ne zahteva nikakvu instalaciju.
Scenario
Firma „Vojvodina Agro" pravi veb portal za partnere u AWS-u, u regionu eu-central-1 (Frankfurt). Zahtevi:
- Lokalna mreža centrale je
172.16.0.0/16, a poslovnice koriste192.168.0.0/16. VPC će kasnije biti povezan sa centralom site-to-site VPN-om. - Portal radi u dve zone dostupnosti.
- Javni subneti: load balancer i NAT gateway — do 50 adresa po zoni.
- Aplikacioni subneti (privatni): do 200 instanci po zoni; izlaz na internet preko NAT gateway-a svoje zone; pristup centrali preko VPN-a.
- Subneti baze (privatni): do 20 adresa po zoni; bez izlaza na internet; pristup samo iz aplikacionih subneta i administratorske mreže centrale
172.16.50.0/24. - Korisnici pristupaju portalu samo preko HTTPS-a (443) na load balancer-u. Aplikacija sluša na portu 8080, a baza je PostgreSQL (5432).
DEO 1 – Projektovanje (svi polaznici)
Korak 1 – Izbor opsega VPC-a
Izaberite CIDR opseg VPC-a veličine /16 iz privatnog opsega 10.0.0.0/8, tako da se ne preklapa sa mrežama centrale i poslovnica. Obrazložite izbor u jednoj rečenici.
Korak 2 – Adresni plan subneta (VLSM)
Popunite tabelu, uzimajući u obzir 5 rezervisanih adresa po subnetu u AWS-u. Za svaki sloj izaberite najmanji prefiks koji zadovoljava zahtev.
| Subnet | Zona | Potrebno adresa | Prefiks | CIDR | Upotrebljivo (−5) |
|---|---|---|---|---|---|
| javni-a | a | 50 | |||
| javni-b | b | 50 | |||
| app-a | a | 200 | |||
| app-b | b | 200 | |||
| baza-a | a | 20 | |||
| baza-b | b | 20 |
Korak 3 – Provera adresnog plana Python skriptom
Napravite fajl provera_vpc.py. Vrednosti ispod su neutralan primer (VPC 10.99.0.0/16, svi subneti /24) koji služi samo da skripta može odmah da se pokrene — zamenite VPC i rečnik SUBNETI svojim planom iz Koraka 1 i 2:
import ipaddress
VPC = "10.99.0.0/16"
LOKALNE_MREZE = {"centrala": "172.16.0.0/16", "poslovnice": "192.168.0.0/16"}
SUBNETI = {
"javni-a": "10.99.1.0/24",
"javni-b": "10.99.2.0/24",
"app-a": "10.99.11.0/24",
"app-b": "10.99.12.0/24",
"baza-a": "10.99.21.0/24",
"baza-b": "10.99.22.0/24",
}
REZERVISANO = 5
greske = 0
vpc = ipaddress.ip_network(VPC)
lokalne = {ime: ipaddress.ip_network(cidr) for ime, cidr in LOKALNE_MREZE.items()}
for ime, lokalna in lokalne.items():
if vpc.overlaps(lokalna):
print(f"GREŠKA: VPC {vpc} se preklapa sa mrežom {ime} ({lokalna})")
greske += 1
mreze = {}
for ime, cidr in SUBNETI.items():
try:
mreze[ime] = ipaddress.ip_network(cidr)
except ValueError as e:
print(f"GREŠKA: {ime} — neispravan CIDR ({e})")
greske += 1
continue
if not mreze[ime].subnet_of(vpc):
print(f"GREŠKA: {ime} {cidr} nije unutar VPC-a {vpc}")
greske += 1
imena = list(mreze)
for i, prvi in enumerate(imena):
for drugi in imena[i + 1:]:
if mreze[prvi].overlaps(mreze[drugi]):
print(f"GREŠKA: {prvi} ({mreze[prvi]}) se preklapa sa {drugi} ({mreze[drugi]})")
greske += 1
print(f"\n{'Subnet':10} {'CIDR':16} {'Upotrebljivo':>12}")
for ime, mreza in mreze.items():
print(f"{ime:10} {str(mreza):16} {mreza.num_addresses - REZERVISANO:>12}")
print("\nPlan je ispravan." if greske == 0 else f"\nPronađeno grešaka: {greske}")
Pokrenite python3 provera_vpc.py sa svojim planom i proverite da skripta prijavljuje „Plan je ispravan." i da kolona „Upotrebljivo" zadovoljava zahteve scenarija. Zatim proverite da li skripta zaista hvata greške — privremeno unesite svaku od sledećih izmena, pokrenite skriptu, pa izmenu vratite:
- subnet
app-bpromenite tako da se preklapa saapp-a(npr. druga polovina mrežeapp-asa prefiksom/25); - za
baza-aupišite adresu koja nije početak mreže (npr..8sa prefiksom/27); VPC = "172.16.0.0/12"(preklapanje sa centralom).
Korak 4 – Tabele ruta
Za svaku tabelu ruta napišite rute (odredište → cilj) i navedite kojim subnetima je pridružena: rt-javni, rt-app-a, rt-app-b, rt-baza. Koristite ciljeve local, igw, nat-a, nat-b i vgw (VPN ka centrali i poslovnicama).
Korak 5 – Security group-e i NACL
- Napišite dolazna pravila za
sg-lb,sg-appisg-bazatako da poštuju zahteve scenarija i princip najmanjih privilegija. Gde god je moguće, koristite reference na druge security group-e. - Napišite NACL za subnete baze (dolazna i odlazna pravila sa rednim brojevima), imajući u vidu da je NACL stateless.
- Nacrtajte dijagram arhitekture (draw.io ili Mermaid) i sačuvajte ga uz plan.
DEO 2 – Izrada u AWS-u (opciono)
U Delu 2 pravite pojednostavljenu verziju plana: VPC 10.30.0.0/16, subnet javni-a sa jednim veb serverom i privatni subnet app-a bez instanci.
Korak 6 – Priprema naloga: bezbednost i budžet
- Prijavite se na AWS konzolu. Ako koristite root nalog, prvo uključite MFA (IAM → Security credentials). Za svakodnevni rad je preporučen poseban korisnik sa administratorskim pravima i MFA.
- Billing and Cost Management → Budgets → Create budget → Use a template → Zero spend budget. Upišite svoju e-poštu. Dobićete poruku čim bilo šta počne da se naplaćuje.
- U gornjem desnom uglu konzole izaberite region Europe (Frankfurt) eu-central-1.
Korak 7 – CloudShell i fajl sa identifikatorima
Otvorite CloudShell (ikona terminala u gornjoj traci konzole). Promenljive u CloudShell-u nestaju ako sesija istekne, pa sve identifikatore upisujte u fajl koji ostaje sačuvan u kućnom folderu:
aws sts get-caller-identity
AZ=$(aws ec2 describe-availability-zones --query 'AvailabilityZones[0].ZoneName' --output text)
echo "AZ=$AZ" > ~/kurs25.env
cat ~/kurs25.env
Ako se sesija prekine, promenljive vraćate sa source ~/kurs25.env.
Korak 8 – VPC i subneti
VPC_ID=$(aws ec2 create-vpc --cidr-block 10.30.0.0/16 \
--tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=kurs25-vpc},{Key=projekat,Value=kurs25}]' \
--query Vpc.VpcId --output text)
echo "VPC_ID=$VPC_ID" >> ~/kurs25.env
PUB_ID=$(aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block 10.30.0.0/26 --availability-zone $AZ \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=kurs25-javni-a},{Key=projekat,Value=kurs25}]' \
--query Subnet.SubnetId --output text)
echo "PUB_ID=$PUB_ID" >> ~/kurs25.env
PRIV_ID=$(aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block 10.30.1.0/24 --availability-zone $AZ \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=kurs25-app-a},{Key=projekat,Value=kurs25}]' \
--query Subnet.SubnetId --output text)
echo "PRIV_ID=$PRIV_ID" >> ~/kurs25.env
aws ec2 describe-subnets --subnet-ids $PUB_ID $PRIV_ID \
--query 'Subnets[].[Tags[?Key==`Name`]|[0].Value,CidrBlock,AvailableIpAddressCount]' --output table
Uporedite kolonu sa brojem dostupnih adresa sa svojim računom iz Dela 1 (64 − 5 i 256 − 5).
Korak 9 – Internet gateway i tabela ruta javnog subneta
IGW_ID=$(aws ec2 create-internet-gateway \
--tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=kurs25-igw},{Key=projekat,Value=kurs25}]' \
--query InternetGateway.InternetGatewayId --output text)
echo "IGW_ID=$IGW_ID" >> ~/kurs25.env
aws ec2 attach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID
RT_ID=$(aws ec2 create-route-table --vpc-id $VPC_ID \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=kurs25-rt-javni},{Key=projekat,Value=kurs25}]' \
--query RouteTable.RouteTableId --output text)
echo "RT_ID=$RT_ID" >> ~/kurs25.env
aws ec2 create-route --route-table-id $RT_ID --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW_ID
aws ec2 associate-route-table --route-table-id $RT_ID --subnet-id $PUB_ID
aws ec2 modify-subnet-attribute --subnet-id $PUB_ID --map-public-ip-on-launch
Uporedite tabelu ruta javnog subneta sa main tabelom, koju koristi privatni subnet:
aws ec2 describe-route-tables --route-table-ids $RT_ID --query 'RouteTables[0].Routes' --output table
aws ec2 describe-route-tables --filters Name=vpc-id,Values=$VPC_ID Name=association.main,Values=true \
--query 'RouteTables[0].Routes' --output table
Korak 10 – Security group za veb server
SG_ID=$(aws ec2 create-security-group --group-name kurs25-web-sg \
--description "Samo HTTP za laboratoriju" --vpc-id $VPC_ID --query GroupId --output text)
echo "SG_ID=$SG_ID" >> ~/kurs25.env
aws ec2 authorize-security-group-ingress --group-id $SG_ID --protocol tcp --port 80 --cidr 0.0.0.0/0
SSH port namerno nije otvoren — za ovu vežbu nije potreban.
Korak 11 – Veb server u javnom subnetu
Skripta koju instanca izvršava pri prvom pokretanju (user data):
cat > ~/web.sh << 'EOF'
#!/bin/bash
dnf install -y nginx
echo "<h1>Modul 25 - veb server u javnom subnetu</h1>" > /usr/share/nginx/html/index.html
systemctl enable --now nginx
EOF
Najnoviji Amazon Linux 2023 image i pokretanje instance:
AMI_ID=$(aws ssm get-parameters --names /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 \
--query 'Parameters[0].Value' --output text)
INST_ID=$(aws ec2 run-instances --image-id $AMI_ID --instance-type t3.micro \
--subnet-id $PUB_ID --security-group-ids $SG_ID --user-data file://$HOME/web.sh \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=kurs25-web},{Key=projekat,Value=kurs25}]' \
--query 'Instances[0].InstanceId' --output text)
echo "INST_ID=$INST_ID" >> ~/kurs25.env
aws ec2 wait instance-running --instance-ids $INST_ID
WEB_IP=$(aws ec2 describe-instances --instance-ids $INST_ID \
--query 'Reservations[0].Instances[0].PublicIpAddress' --output text)
echo "WEB_IP=$WEB_IP" >> ~/kurs25.env
echo $WEB_IP
Ako
t3.micronije označen kao Free tier eligible za vaš nalog ili region, upotrebite tip koji konzola u EC2 → Launch instance označava kao besplatan (npr.t2.micro).
Sačekajte 2–3 minuta da se nginx instalira, pa proverite iz CloudShell-a i iz svog pregledača (http://<WEB_IP>):
curl -m 5 http://$WEB_IP
Proverite i privatnu adresu instance: aws ec2 describe-instances --instance-ids $INST_ID --query 'Reservations[0].Instances[0].PrivateIpAddress' --output text. U kom je opsegu? Da li instanca „zna" za svoju javnu adresu (Tema 7)?
Korak 12 – Network ACL za javni subnet
Napravite NACL sa pravilima iz Teme 10 i pridružite je javnom subnetu:
NACL_ID=$(aws ec2 create-network-acl --vpc-id $VPC_ID \
--tag-specifications 'ResourceType=network-acl,Tags=[{Key=Name,Value=kurs25-nacl-javni},{Key=projekat,Value=kurs25}]' \
--query NetworkAcl.NetworkAclId --output text)
echo "NACL_ID=$NACL_ID" >> ~/kurs25.env
aws ec2 create-network-acl-entry --network-acl-id $NACL_ID --ingress --rule-number 100 \
--protocol tcp --port-range From=80,To=80 --cidr-block 0.0.0.0/0 --rule-action allow
aws ec2 create-network-acl-entry --network-acl-id $NACL_ID --ingress --rule-number 110 \
--protocol tcp --port-range From=1024,To=65535 --cidr-block 0.0.0.0/0 --rule-action allow
aws ec2 create-network-acl-entry --network-acl-id $NACL_ID --egress --rule-number 100 \
--protocol tcp --port-range From=1024,To=65535 --cidr-block 0.0.0.0/0 --rule-action allow
aws ec2 create-network-acl-entry --network-acl-id $NACL_ID --egress --rule-number 110 \
--protocol tcp --port-range From=80,To=80 --cidr-block 0.0.0.0/0 --rule-action allow
aws ec2 create-network-acl-entry --network-acl-id $NACL_ID --egress --rule-number 120 \
--protocol tcp --port-range From=443,To=443 --cidr-block 0.0.0.0/0 --rule-action allow
ASSOC_ID=$(aws ec2 describe-network-acls --filters Name=association.subnet-id,Values=$PUB_ID \
--query "NetworkAcls[0].Associations[?SubnetId=='$PUB_ID'].NetworkAclAssociationId" --output text)
aws ec2 replace-network-acl-association --association-id $ASSOC_ID --network-acl-id $NACL_ID
aws ec2 describe-network-acls --network-acl-ids $NACL_ID --query 'NetworkAcls[0].Entries' --output table
curl -m 5 http://$WEB_IP
Sajt i dalje radi. U tabeli pravila pronađite i implicitna pravila * (broj 32767) koja odbijaju sve ostalo.
Korak 13 – Dijagnostička vežba: dva kvara
Kvar A. Izvršite:
aws ec2 delete-route --route-table-id $RT_ID --destination-cidr-block 0.0.0.0/0
curl -m 5 http://$WEB_IP
Sajt više ne odgovara. Bez gledanja u komandu koju ste upravo izvršili, pronađite uzrok proverom pet uslova iz Teme 7 — koristite describe-internet-gateways, describe-route-tables, describe-instances, describe-security-groups i describe-network-acls. Zatim ispravite kvar i potvrdite da sajt ponovo radi.
Kvar B. Izvršite:
aws ec2 delete-network-acl-entry --network-acl-id $NACL_ID --egress --rule-number 100
curl -m 5 http://$WEB_IP
Sajt ponovo ne odgovara, iako se security group nije menjala i iako dolazno NACL pravilo za port 80 i dalje postoji. Objasnite zašto, ispravite kvar i potvrdite da sajt radi.
Korak 14 – Brisanje svih resursa (obavezno)
Resurse brišite redosledom koji poštuje zavisnosti:
source ~/kurs25.env
aws ec2 terminate-instances --instance-ids $INST_ID
aws ec2 wait instance-terminated --instance-ids $INST_ID
aws ec2 delete-security-group --group-id $SG_ID
aws ec2 delete-subnet --subnet-id $PUB_ID
aws ec2 delete-subnet --subnet-id $PRIV_ID
aws ec2 delete-network-acl --network-acl-id $NACL_ID
aws ec2 detach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID
aws ec2 delete-internet-gateway --internet-gateway-id $IGW_ID
aws ec2 delete-route-table --route-table-id $RT_ID
aws ec2 delete-vpc --vpc-id $VPC_ID
Provera da ništa nije ostalo:
aws ec2 describe-vpcs --filters Name=tag:projekat,Values=kurs25 --query 'Vpcs[].VpcId'
aws ec2 describe-instances --filters Name=tag:projekat,Values=kurs25 Name=instance-state-name,Values=running,stopped \
--query 'Reservations[].Instances[].InstanceId'
Oba odgovora treba da budu prazne liste ([]). Sutradan pogledajte Billing → Bills i proverite da nema neočekivanih stavki.
Komande za proveru
| Komanda | Šta proverava |
|---|---|
python3 provera_vpc.py | Adresni plan: pripadnost VPC-u, preklapanja, upotrebljive adrese |
aws ec2 describe-subnets --subnet-ids ... | CIDR i broj dostupnih adresa subneta |
aws ec2 describe-route-tables --route-table-ids ... | Rute i pridruženi subneti |
aws ec2 describe-internet-gateways --internet-gateway-ids ... | Da li je IGW pridružen VPC-u |
aws ec2 describe-security-groups --group-ids ... | Pravila security group-e |
aws ec2 describe-network-acls --network-acl-ids ... | NACL pravila i pridruženi subneti |
aws ec2 describe-instances --instance-ids ... | Stanje instance, privatna i javna adresa |
curl -m 5 http://<adresa> | Dostupnost veb servera, sa ograničenjem od 5 sekundi |
Najčešće greške
AZ,VPC_IDi ostale promenljive su prazne jer je CloudShell sesija istekla — izvršitesource ~/kurs25.env.- Nije izabran region
eu-central-1, pa se resursi prave (i traže) u drugom regionu. - Instanca nema javnu IP adresu jer
map-public-ip-on-launchnije uključen pre pokretanja instance. curlodmah posle pokretanja ne radi — nginx se još instalira (sačekajte 2–3 minuta).- Brisanje subneta ili security group-e ne uspeva jer instanca još nije potpuno ugašena — sačekajte
wait instance-terminated. - Zaboravljeno brisanje resursa na kraju.
Postupak rešavanja problema
- Region i identifikatori:
aws configure get region,cat ~/kurs25.env. - Put ka internetu: IGW pridružen VPC-u, a tabela ruta subneta ima
0.0.0.0/0→ IGW. - Adresa: instanca ima javnu IP adresu i u stanju je running.
- Pravila: security group (dolazno), NACL (dolazno i odlazno, uključujući efemerne portove).
- Servis: da li je nginx instaliran i pokrenut (EC2 → instanca → Actions → Monitor and troubleshoot → Get system log).
Završna provera
- [ ] Deo 1: adresni plan popunjen, skripta prijavljuje „Plan je ispravan." i hvata sve tri namerne greške.
- [ ] Deo 1: napisane su tabele ruta, security group-e, NACL za bazu i dijagram.
- [ ] Deo 2: veb server je bio dostupan sa interneta preko javne adrese.
- [ ] Deo 2: oba kvara iz Koraka 13 su dijagnostikovana i ispravljena.
- [ ] Deo 2: svi resursi su obrisani i provera vraća prazne liste.
Dodatni izazov
- NAT gateway za privatni subnet (naplaćuje se po satu — ceo izazov uradite u jednom navratu, za manje od sat vremena, i odmah obrišite): pre Koraka 14 napravite Elastic IP adresu i NAT gateway u javnom subnetu, posebnu tabelu ruta za privatni subnet sa rutom
0.0.0.0/0→ NAT gateway, a zatim obrišite NAT gateway i oslobodite Elastic IP adresu. Napišite komande i redosled. - Isti plan u Azure-u: prevedite plan iz Dela 1 u Azure pojmove (VNet, subneti, NSG, NAT Gateway, Application Gateway, VPN Gateway). Navedite jednu razliku u ponašanju koja utiče na plan.
Rešenje
Kompletno rešenje dostupno je u /resenja/modul-25/04-laboratorijska-vezba-resenje.md.
📖 Prikaži rešenje
Rešenje laboratorijske vežbe – Modul 25
DEO 1 – Projektovanje
Korak 1 – Opseg VPC-a
10.30.0.0/16 — pripada opsegu 10.0.0.0/8, ne preklapa se ni sa centralom (172.16.0.0/16) ni sa poslovnicama (192.168.0.0/16), i ostavlja prostor za druge VPC-ove (npr. testni 10.31.0.0/16). Prihvata se svaki /16 iz 10.0.0.0/8 koji se ni sa čim ne preklapa.
Korak 2 – Adresni plan (VLSM)
| Subnet | Zona | Potrebno | Prefiks | CIDR | Upotrebljivo (−5) |
|---|---|---|---|---|---|
| javni-a | a | 50 | /26 | 10.30.0.0/26 | 59 |
| javni-b | b | 50 | /26 | 10.30.0.64/26 | 59 |
| app-a | a | 200 | /24 | 10.30.1.0/24 | 251 |
| app-b | b | 200 | /24 | 10.30.2.0/24 | 251 |
| baza-a | a | 20 | /27 | 10.30.3.0/27 | 27 |
| baza-b | b | 20 | /27 | 10.30.3.32/27 | 27 |
Obrazloženje najmanjih prefiksa: za 50 adresa /27 nije dovoljan (32 − 5 = 27), pa je potreban /26 (59). Za 200 adresa /25 nije dovoljan (128 − 5 = 123), pa je potreban /24 (251). Za 20 adresa /28 nije dovoljan (16 − 5 = 11), pa je potreban /27 (27). Prostor 10.30.0.128/25 i 10.30.3.64 i dalje ostaje slobodan za rast.
Korak 3 – Izlaz skripte za ovaj plan
Subnet CIDR Upotrebljivo
javni-a 10.30.0.0/26 59
javni-b 10.30.0.64/26 59
app-a 10.30.1.0/24 251
app-b 10.30.2.0/24 251
baza-a 10.30.3.0/27 27
baza-b 10.30.3.32/27 27
Plan je ispravan.
Provera namernih grešaka:
| Izmena | Poruka skripte |
|---|---|
"app-b": "10.30.1.128/25" | GREŠKA: app-a (10.30.1.0/24) se preklapa sa app-b (10.30.1.128/25) |
"baza-a": "10.30.3.8/27" | GREŠKA: baza-a — neispravan CIDR (10.30.3.8/27 has host bits set) |
VPC = "172.16.0.0/12" | GREŠKA: VPC 172.16.0.0/12 se preklapa sa mrežom centrala (172.16.0.0/16), plus po jedna greška za svaki subnet koji više nije unutar VPC-a (ukupno 7) |
Korak 4 – Tabele ruta
rt-javni — pridružena javni-a i javni-b:
| Odredište | Cilj |
|---|---|
| 10.30.0.0/16 | local |
| 0.0.0.0/0 | igw |
rt-app-a — pridružena app-a:
| Odredište | Cilj |
|---|---|
| 10.30.0.0/16 | local |
| 172.16.0.0/16 | vgw |
| 192.168.0.0/16 | vgw |
| 0.0.0.0/0 | nat-a |
rt-app-b — pridružena app-b: isto kao rt-app-a, ali 0.0.0.0/0 → nat-b (NAT gateway u sopstvenoj zoni).
rt-baza — pridružena baza-a i baza-b:
| Odredište | Cilj |
|---|---|
| 10.30.0.0/16 | local |
| 172.16.0.0/16 | vgw |
Baza nema rutu 0.0.0.0/0, pa nema izlaz na internet. Ruta ka centrali postoji zbog administratorske mreže 172.16.50.0/24 (može i uže: 172.16.50.0/24 → vgw). Main tabela VPC-a ostaje samo sa rutom local. Rute ka vgw mogu biti i propagirane sa VPN gateway-a (BGP), umesto statičkih.
Korak 5 – Security group-e i NACL
Security group-e:
| SG | Protokol/port | Izvor |
|---|---|---|
| sg-lb | TCP 443 | 0.0.0.0/0 |
| sg-app | TCP 8080 | sg-lb |
| sg-app | TCP 22 | 172.16.50.0/24 |
| sg-baza | TCP 5432 | sg-app |
| sg-baza | TCP 5432 | 172.16.50.0/24 (administracija baze iz centrale) |
(Poslednje pravilo je prihvatljivo i bez njega, ako administratori baze pristupaju preko aplikacionog servera. SSH ka bazi nije potreban ako je baza upravljana usluga.)
NACL za subnete baze:
| Smer | Br. | Protokol | Portovi | Izvor/odredište | Akcija |
|---|---|---|---|---|---|
| Dolazno | 100 | TCP | 5432 | 10.30.1.0/24 | Dozvoli |
| Dolazno | 110 | TCP | 5432 | 10.30.2.0/24 | Dozvoli |
| Dolazno | 120 | TCP | 5432 | 172.16.50.0/24 | Dozvoli |
| Dolazno | * | Sve | Sve | 0.0.0.0/0 | Odbij |
| Odlazno | 100 | TCP | 1024–65535 | 10.30.1.0/24 | Dozvoli |
| Odlazno | 110 | TCP | 1024–65535 | 10.30.2.0/24 | Dozvoli |
| Odlazno | 120 | TCP | 1024–65535 | 172.16.50.0/24 | Dozvoli |
| Odlazno | * | Sve | Sve | 0.0.0.0/0 | Odbij |
Ako se baza replicira između zona, dodaju se i pravila za saobraćaj između 10.30.3.0/27 i 10.30.3.32/27.
Dijagram (Mermaid):
graph TB
INET["Internet"] --> IGW["IGW"]
subgraph VPC["VPC 10.30.0.0/16 (eu-central-1)"]
subgraph A["Zona a"]
JA["javni-a 10.30.0.0/26<br/>LB, NAT-a"]
AA["app-a 10.30.1.0/24"]
BA["baza-a 10.30.3.0/27"]
end
subgraph B["Zona b"]
JB["javni-b 10.30.0.64/26<br/>LB, NAT-b"]
AB["app-b 10.30.2.0/24"]
BB["baza-b 10.30.3.32/27"]
end
end
IGW --> JA
IGW --> JB
JA --> AA --> BA
JB --> AB --> BB
VGW["VPN gateway"] --- AA
VGW --- AB
VGW --- BA
CEN["Centrala 172.16.0.0/16<br/>Poslovnice 192.168.0.0/16"] --- VGW
DEO 2 – AWS
Korak 8 – Očekivani izlaz describe-subnets
-------------------------------------------------
| DescribeSubnets |
+-----------------+----------------+------------+
| kurs25-javni-a | 10.30.0.0/26 | 59 |
| kurs25-app-a | 10.30.1.0/24 | 251 |
+-----------------+----------------+------------+
Broj dostupnih adresa se poklapa sa računom iz Dela 1 (64 − 5 i 256 − 5).
Korak 9 – Tabele ruta
rt-javni ima dve rute: 10.30.0.0/16 → local i 0.0.0.0/0 → igw-.... Main tabela, koju koristi privatni subnet app-a, ima samo local — zato je app-a privatni.
Korak 11 – Veb server
curl vraća <h1>Modul 25 - veb server u javnom subnetu</h1>, a isti sadržaj se vidi u pregledaču. Privatna adresa instance je iz opsega 10.30.0.0/26 (npr. 10.30.0.37). Instanca „ne zna" za svoju javnu adresu — u operativnom sistemu (ip addr) postoji samo privatna, jer internet gateway radi statički 1:1 NAT (Tema 7).
Korak 12 – NACL
Sajt i dalje radi, jer NACL dozvoljava dolazni TCP 80 i odlazne odgovore ka efemernim portovima. U tabeli pravila postoje i implicitna pravila broj 32767 sa akcijom deny za oba smera.
Korak 13 – Dijagnostika
Kvar A — obrisana podrazumevana ruta.
| Provera | Rezultat |
|---|---|
describe-internet-gateways | IGW je pridružen VPC-u (available) |
describe-route-tables --route-table-ids $RT_ID | Postoji samo local; nema 0.0.0.0/0 → igw |
describe-instances | Instanca running, ima javnu IP adresu |
describe-security-groups | TCP 80 iz 0.0.0.0/0 dozvoljen |
describe-network-acls | Pravila nepromenjena |
Uzrok: subnet nema rutu ka internetu. Paketi od klijenta stižu do instance, ali odgovori nemaju kuda da se vrate, pa curl ističe posle 5 sekundi. Ispravka:
aws ec2 create-route --route-table-id $RT_ID --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW_ID
Kvar B — obrisano odlazno NACL pravilo 100.
Dolazni zahtev na port 80 prolazi (dolazno pravilo 100), a security group je stateful i dozvoljava odgovor. Ali NACL je stateless: odgovor servera ide sa porta 80 ka efemernom portu klijenta (npr. 51734). Posle brisanja pravila 100 nijedno odlazno pravilo ne dozvoljava TCP ka portovima 1024–65535 (pravila 110 i 120 dozvoljavaju samo odredišne portove 80 i 443), pa implicitno pravilo * odbacuje odgovor. Ispravka:
aws ec2 create-network-acl-entry --network-acl-id $NACL_ID --egress --rule-number 100 \
--protocol tcp --port-range From=1024,To=65535 --cidr-block 0.0.0.0/0 --rule-action allow
Pouka: simptom je u oba slučaja isti (istek vremena), ali je uzrok na različitom mestu. Sistematska provera pet uslova (Tema 7) i razumevanje stateful naspram stateless filtriranja (Modul 16) vode do uzroka bez nagađanja.
Korak 14 – Brisanje
Obe provere vraćaju []. Ako delete-security-group ili delete-subnet prijave DependencyViolation, mrežni interfejs instance još nije uklonjen — sačekajte nekoliko sekundi i ponovite komandu.
Rešenje dodatnog izazova
1. NAT gateway za privatni subnet
Izvršava se pre Koraka 14, u jednom navratu:
EIP_ALLOC=$(aws ec2 allocate-address --domain vpc --query AllocationId --output text)
NAT_ID=$(aws ec2 create-nat-gateway --subnet-id $PUB_ID --allocation-id $EIP_ALLOC \
--query NatGateway.NatGatewayId --output text)
aws ec2 wait nat-gateway-available --nat-gateway-ids $NAT_ID
PRIV_RT_ID=$(aws ec2 create-route-table --vpc-id $VPC_ID --query RouteTable.RouteTableId --output text)
aws ec2 create-route --route-table-id $PRIV_RT_ID --destination-cidr-block 0.0.0.0/0 --nat-gateway-id $NAT_ID
aws ec2 associate-route-table --route-table-id $PRIV_RT_ID --subnet-id $PRIV_ID
aws ec2 describe-route-tables --route-table-ids $PRIV_RT_ID --query 'RouteTables[0].Routes' --output table
Brisanje, odmah posle provere:
aws ec2 delete-nat-gateway --nat-gateway-id $NAT_ID
aws ec2 wait nat-gateway-deleted --nat-gateway-ids $NAT_ID
aws ec2 release-address --allocation-id $EIP_ALLOC
Zatim Korak 14 kao i inače, uz dodatnu komandu posle brisanja subneta:
aws ec2 delete-route-table --route-table-id $PRIV_RT_ID
Redosled i razlozi:
- NAT gateway se pravi u javnom subnetu, jer mu je potreban put ka IGW-u.
- Privatni subnet dobija sopstvenu tabelu ruta; main tabela se ne menja.
- Elastic IP se oslobađa tek kada je NAT gateway obrisan, jer je adresa za njega vezana. Zauzeta, a neiskorišćena Elastic IP adresa se takođe naplaćuje.
Napomena o NACL-u: saobraćaj privatnih instanci ka NAT gateway-u ulazi u javni subnet. Uz NACL iz Koraka 12, dolazni HTTPS iz 10.30.1.0/24 bio bi odbijen. Da bi privatne instance preuzimale ažuriranja preko HTTPS-a, dodaje se dolazno pravilo, npr. br. 120: TCP 443 iz 10.30.1.0/24. Uz to, već postojeća pravila moraju pokrivati i odgovore u oba smera.
2. Plan u Azure-u
| AWS (Deo 1) | Azure |
|---|---|
| VPC 10.30.0.0/16 | Virtual Network (VNet) 10.30.0.0/16 |
| Subneti javni/app/baza | Subneti (npr. snet-javni, snet-app, snet-baza) |
| Tabele ruta | Route table (UDR) pridružene subnetima |
| Security group-e | Network Security Group (NSG) na NIC-ovima ili subnetima; umesto referenci na SG koriste se Application Security Groups |
| NACL za bazu | NSG pridružena subnetu baze (stateful) |
| NAT gateway po zoni | Azure NAT Gateway (zonski) pridružen subnetima |
| Application Load Balancer | Application Gateway (L7) |
| Virtual private gateway | VPN Gateway (aktivno-aktivni, sa BGP-om) |
Razlika koja utiče na plan: Azure subneti su regionalni i obuhvataju sve zone. Za dve zone zato nisu potrebni posebni subneti po zoni — dovoljni su javni, aplikacioni i subnet baze, a zone se biraju na nivou resursa (VM, NAT Gateway, Application Gateway). Druga razlika: Azure NSG je stateful, pa se NACL pravila za efemerne portove ne prenose.