<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Muhammad Usman Tahir</title>
    <description>The latest articles on Forem by Muhammad Usman Tahir (@usman_tahir).</description>
    <link>https://forem.com/usman_tahir</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3722492%2F82d9ea4b-d8e5-4b64-bff8-78f97bb33655.jpg</url>
      <title>Forem: Muhammad Usman Tahir</title>
      <link>https://forem.com/usman_tahir</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/usman_tahir"/>
    <language>en</language>
    <item>
      <title>Why My EC2 Instance Was Running but Still Not Accessible</title>
      <dc:creator>Muhammad Usman Tahir</dc:creator>
      <pubDate>Wed, 21 Jan 2026 09:44:23 +0000</pubDate>
      <link>https://forem.com/usman_tahir/why-my-ec2-instance-was-running-but-still-not-accessible-17aa</link>
      <guid>https://forem.com/usman_tahir/why-my-ec2-instance-was-running-but-still-not-accessible-17aa</guid>
      <description>&lt;p&gt;When I launched my first Amazon EC2 instance, everything looked fine in the AWS Console.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instance state: Running&lt;/li&gt;
&lt;li&gt;System status checks: Passed&lt;/li&gt;
&lt;li&gt;Public IP assigned: Yes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But when I tried to connect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSH → Timeout&lt;/li&gt;
&lt;li&gt;Browser → Connection refused&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first, this felt confusing. If the instance is running, why can’t I access it?&lt;br&gt;
This post explains &lt;strong&gt;why this happens&lt;/strong&gt;, what I misunderstood, and how I fixed it.&lt;br&gt;
&lt;strong&gt;The Problem&lt;/strong&gt;&lt;br&gt;
I faced two common symptoms:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; &lt;strong&gt;SSH Access Failed&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh ec2-user@192.168.1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connection timed out&lt;/li&gt;
&lt;li&gt;Or connection refused&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; &lt;strong&gt;Web App Not Opening&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browser showed "This site can’t be reached"
Despite the EC2 instance being healthy, &lt;strong&gt;network access was blocked&lt;/strong&gt;.
&lt;strong&gt;The Key Realization&lt;/strong&gt;
&lt;strong&gt;Running EC2 ≠ Accessible EC2&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AWS separates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compute (EC2 instance)&lt;/li&gt;
&lt;li&gt;Network security (Security Groups + NACLs)&lt;/li&gt;
&lt;li&gt;Networking (Public vs Private IP)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If &lt;strong&gt;any one&lt;/strong&gt; of these is misconfigured, access will fail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security Groups vs NACLs (Most Common Confusion)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Security Groups&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Act as a &lt;strong&gt;virtual firewall&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Work at the &lt;strong&gt;instance level&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Are &lt;strong&gt;stateful&lt;/strong&gt; (responses are automatically allowed)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If inbound traffic is not explicitly allowed →  access denied.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Network ACLs (NACLs)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;wOrk at the &lt;strong&gt;subnet level&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Are &lt;strong&gt;stateless&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Require both inbound &lt;strong&gt;and outbound&lt;/strong&gt; rules.
Even if your Security Group is correct, a restrictive NACL can still block traffic.
&lt;strong&gt;Required Ports Explained&lt;/strong&gt;
Depending on your use case, these ports must be open:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Use Case&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Port&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Protocol&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;TCP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP&lt;/td&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;TCP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTPS&lt;/td&gt;
&lt;td&gt;443&lt;/td&gt;
&lt;td&gt;TCP&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Missing even one required port = &lt;strong&gt;connection failure&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Public IP vs Private IP (Critical Detail)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Public IP&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Required to access EC2 from the internet&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changes when instance is stopped/started (unless Elastic IP is used)&lt;br&gt;
&lt;strong&gt;Private IP&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Works &lt;strong&gt;only inside the VPC&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not accessible from your local machine&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you use a &lt;strong&gt;private IP&lt;/strong&gt; from your laptop, the connection will never work.&lt;br&gt;
&lt;strong&gt;The Fix: Security Group Configuration&lt;/strong&gt;&lt;br&gt;
My issue was missing inbound rules in the Security Group.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Allow SSH Access (Port 22)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "IpProtocol": "tcp",
  "FromPort": 22,
  "ToPort": 22,
  "IpRanges": [
    {
      "CidrIp": "0.0.0.0/0",
      "Description": "Allow SSH access"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example: Allow HTTP Access (Port 80)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "IpProtocol": "tcp",
  "FromPort": 80,
  "ToPort": 80,
  "IpRanges": [
    {
      "CidrIp": "0.0.0.0/0",
      "Description": "Allow HTTP traffic"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For production, never keep SSH open to 0.0.0.0/0. Restrict it to your IP.&lt;br&gt;
&lt;strong&gt;What I Checked Step-by-Step&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;EC2 instance state → &lt;strong&gt;Running&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Public IP assigned → &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Security Group inbound rules → &lt;strong&gt;Missing&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;NACL rules → &lt;strong&gt;Allowed&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Correct username used (ec2-user, ubuntu, etc.)&lt;/li&gt;
&lt;li&gt;Correct key permissions (chmod 400)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After fixing the Security Group, SSH worked instantly.&lt;br&gt;
&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2 running status only confirms compute availability&lt;/li&gt;
&lt;li&gt;Network access depends on &lt;strong&gt;Security Groups + NACLs&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Security Groups must explicitly allow required ports&lt;/li&gt;
&lt;li&gt;Public IP is mandatory for internet access&lt;/li&gt;
&lt;li&gt;AWS prioritizes &lt;strong&gt;security over convenience&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
This issue taught me how &lt;strong&gt;layered AWS security&lt;/strong&gt; really is.&lt;br&gt;
Instead of assuming something is broken, it’s better to trace the request path:&lt;br&gt;
&lt;strong&gt;Client → Internet → Security Group → NACL → EC2&lt;/strong&gt;&lt;br&gt;
Once I understood this flow, debugging became much easier.&lt;br&gt;
If you’re learning AWS, trust me everyone hits this problem at least once.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ec2</category>
      <category>cloud</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Why My S3 Object URL Still Gave Access Denied (And How I Fixed It)</title>
      <dc:creator>Muhammad Usman Tahir</dc:creator>
      <pubDate>Wed, 21 Jan 2026 09:22:36 +0000</pubDate>
      <link>https://forem.com/usman_tahir/why-my-s3-object-url-still-gave-access-denied-and-how-i-fixed-it-54p9</link>
      <guid>https://forem.com/usman_tahir/why-my-s3-object-url-still-gave-access-denied-and-how-i-fixed-it-54p9</guid>
      <description>&lt;p&gt;When you’re new to AWS S3, one of the most confusing things is public access.&lt;br&gt;
Recently, I faced an issue where I uploaded a file to S3, disabled Block all public access, but still got Access Denied when opening the Object URL.&lt;br&gt;
Here’s what happened, why it happened, and how I fixed it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;&lt;br&gt;
I uploaded a file to an S3 bucket and wanted to access it using the &lt;strong&gt;Object URL&lt;/strong&gt;.&lt;br&gt;
Steps I had already taken:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uploaded the file successfully&lt;/li&gt;
&lt;li&gt;Disabled &lt;strong&gt;Block all public access&lt;/strong&gt; at the bucket level&lt;/li&gt;
&lt;li&gt;Tried opening the Object URL in the browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Result: &lt;strong&gt;AccessDenied&lt;/strong&gt;&lt;br&gt;
At this point, I thought:&lt;br&gt;
"Public access is disabled, so why is it still denying access?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Important Concept I Missed&lt;/strong&gt;&lt;br&gt;
Disabling &lt;strong&gt;Block all public access&lt;/strong&gt; does &lt;strong&gt;NOT&lt;/strong&gt; automatically make your objects public.&lt;br&gt;
It only means:&lt;br&gt;
AWS will now allow you to create public permissions — but you still have to define them.&lt;br&gt;
So unless you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a &lt;strong&gt;bucket policy&lt;/strong&gt;, or&lt;/li&gt;
&lt;li&gt;Make the object public via ACL (not recommended anymore)
Your objects will remain private.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Solution That Worked&lt;/strong&gt;&lt;br&gt;
I added a &lt;strong&gt;bucket policy&lt;/strong&gt; to explicitly allow public read access for objects.&lt;br&gt;
Here is the policy I used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::usman-bucket-v1/*"
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What This Policy Does&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allows &lt;strong&gt;anyone&lt;/strong&gt; (Principal: "*")&lt;/li&gt;
&lt;li&gt;To &lt;strong&gt;read objects&lt;/strong&gt; (s3:GetObject)&lt;/li&gt;
&lt;li&gt;Inside my bucket (usman-bucket-v1/*)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After adding this policy, I refreshed the Object URL and it worked.&lt;br&gt;
&lt;strong&gt;Why AWS Does This (Security Reason)&lt;/strong&gt;&lt;br&gt;
AWS follows &lt;strong&gt;secure-by-default&lt;/strong&gt; principles.&lt;br&gt;
Even if public access blocking is disabled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Objects are still private&lt;/li&gt;
&lt;li&gt;You must explicitly allow public access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This prevents accidental data leaks, especially in production environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important Warning&lt;/strong&gt;&lt;br&gt;
This policy makes &lt;strong&gt;all objects in the bucket public&lt;/strong&gt;.&lt;br&gt;
Do &lt;strong&gt;NOT&lt;/strong&gt; use this for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sensitive files&lt;/li&gt;
&lt;li&gt;User data&lt;/li&gt;
&lt;li&gt;Production buckets without proper review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Safer Alternatives&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;CloudFront + OAC&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;pre-signed URLs&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Restrict access to specific IPs or principals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Disabling Block all public access ≠ public files&lt;/li&gt;
&lt;li&gt;You still need a bucket policy&lt;/li&gt;
&lt;li&gt;AWS forces explicit permission for security&lt;/li&gt;
&lt;li&gt;Bucket policies are powerful — use carefully&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
This small issue helped me better understand how S3 security actually works.&lt;br&gt;
If you're learning AWS (like me), these "Access Denied" errors are not failures — they’re lessons.&lt;br&gt;
If this post helped you, feel free to share or drop a comment on dev.to.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>s3</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
