Flask web app not responding to external requests on EC2 - python-2.7

I've got a very simple Flask application that I'm hosting on an Amazon EC2 node and for whatever reason I can't see it externally. The flask app is here
from flask import Flask
app = Flask(__name__)
app.config['DEBUG'] = False
#app.route('/')
def hello_world():
return 'Hello World!'
#app.route('/p1')
def p1():
return "P1!!!"
if __name__ == '__main__':
app.run(host='0.0.0.0')
When I run the script it looks like the server is running fine, so in my browser (on a different computer) I put the following :5000 (the IP address I pull off of AWS). What's interesting is that it just seems to hang, and eventually produces an error. My guess is that I'm missing some configuration in AWS but I don't know what it is. Any help would be greatly appreciated
EDIT I tried deploying the app on my local machine. And when I try to access it from the browser using localhost:5000, it works. When I replace localhost with my IP address, it fails

Found this question while searching for a solution to the same issue.
edit run.py to enable flask to respond to requests from other than localhost.
this example enables responding to requests from anywhere. good security policies would use something more restrictive.
app.run(host='0.0.0.0')
in the AWS control panel go to EC2: select instance.
the browser should be pointed to the address from 'Public DNS (IPv4)'
(the ip# from IPv4 Public IP might also be useful)
look for 'Security groups': right-click to open the security group on a new page.
check inbound rules.
by default, flask binds to port 5000. add rule permitting incoming TCP traffic on port 5000.
while good security protocol should limit the number of ports left open and the range of IP's permitted to connect, it might be easier to permit 'anywhere' to connect over 'all tcp'.
NB: check if the default port has been changed in the flask config file run.py
ie: line below changes port from the default 5000 to 3000.
app.run(debug=True, port=3000)
Can also check if the flask instance is working locally by ssh'ing to the server and using a local instance of the lynx text browser to verify the port is responding. ie
lynx localhost:5000

Was able to ultimately answer my own question, both really
The problem I was having on AWS was that my inbound for that EC2 was not allowing access through the ports that I would need.
When I tried running it on my local machine at work, firewall settings change the address of localhost (and my IP) so that's why I couldn't access it outside of using localhost:5000

In your EC2 instance, the security group is what restricting your entry to the website.
Go to AWS portal, select your instance
Locate the security group and click the name
in the inbound rule window, select add rule
Not a recommended security practice but to get it running, select All TCP
add '0.0.0.0' in the source
your website will be running

I faced a similar issue in which the Flask app on EC2 instance was not responding. Turns out that I had to modify the inbound rules because:
The default security groups and newly created security groups include default rules that do not enable you to access your instance from the internet.
In order to modify the inbound rules, go to:
Instances dashboard > Security > Security Groups (go to your security group) > Edit Inbound Rules > Add Rule.
Fill the values:
Type -> Custom TCP
Protocol -> TCP
Port range -> 5000 (If your flask app is running on default port)
Source -> Your IP or 0.0.0.0/0 if you want to allow all traffic. You can also select My IP from source dropdown. This will automatically get your IP.
Save and you are good to go!

As you are already using host="0.0.0.0" in your app it should be accessible from anywhere. The only think blocking it is your aws security group inbound rules. Add a All TCP inbound rule for port 0-65535 (your app port should be in this range) with source 0.0.0.0/0 and it should work.

Related

Can't reach to an AWS EC2 instance website

I just launched a instance on AWS and I'm trying to open the website. So I copy the Public IPv4 address and paste it on my page. But it always returns This site can’t be reached 35.78.183.239 took too long to respond.
I've changed my firewall setting to access google chrome and set security groups HTTP, HTTPS. I can't figure out where the problem is. Any suggestions?
You didn't specify what webserver or AMI is on your EC2 instance.
You need to setup an AMI or manually install and setup a webserver for anything to show, otherwise the EC2 instance, while reachable, will not respond.
Make sure that ssh access is enabled and try ssh into the machine. If you can successfully login, then you know the instance is reachable and the problem is with your webserver software. This will help you debug.
What port is your application running on? When you enable HTTP and HTTPS it only allows ports 80 and 443 on the security group. This won't help if your application runs on a different port, so you'll need to add that to your security group to allow inbound traffic.

EC2 instance refused to connect

I have a site built on NodeJS, which I am currently trying to deploy on the free tier on AWS.
So far I have created an instance, launched it, I can connect via SSH (console) to my instance, and have successfully pulled my files from my Git repository. However, when I try to browse my public DNS, I get: http://ec2-13-234-136-30.ap-south-1.compute.amazonaws.com:2222 took too long to respond.
I have also had a look at the settings on security group (as recommended on a different post) and ensured that inbound and outbound 'HTTP' and 'HTTPS' traffic are allowed (screenshot below):
Inbound settings: Inbound settings
Outbound settings: enter image description here
Any ideas on what else could be causing this issue? I would greatly appreciate your help. Thanks.
Your security configuration is too permissive, please limit to the port and protocols you are using.
Given that your firewall is off, which you should definitely check to confirm,
I guess you start NodeJs server binding to hostname 127.0.0.1, which allows only local traffics from EC2 instance.
Try changing it to 0.0.0.0, which allows public traffic and see if that solves your problem.

AWS EC2 security group https vs tcp vs ssh

I am confused about configuring the EC2 security group settings.
There are three options (TCP, SSH, HTTPS) and each of them requires you to add an IP/port number.
For context, in my work I'm usually running Flask apps over EC2 and I only want particular people to view them. My question is understanding the difference between TCP, SSH, and HTTPs but more importantly which of these are important for me to configure.
Within the EC2 Console, under Security Groups:
SSH and HTTPS in the Type dropdown, are presets which set the port to 22 and 443 respectively.
TCP is the protocol. Both SSH and HTTPS are TCP.
If you're running a server which you want to expose on a non standard port, you can select Custom TCP Rule, then set the port acordingly.
You should probably have one security group that allows SSH traffic, then assign this security group to the EC2 instances you wish to shell into:
Then have a separate security group that allows the webserver traffic, in this case I also have one for port 80, aswell as 443:
Of course you will then need a server running on that EC2 instance to receive the traffic. This might be a reverse proxy like nginx, which then proxies traffic to the correct port for your app server (run your flask app with something like gunicorn in production).
If nginx and gunicorn are running on the same box, and say gunicorn serves on port 8000, then you wouldn't need a security group for this as it's loopback traffic. Your nginx configuration points to port 8000.
However if you have a separate EC2 instance running gunicorn, you might wish to set up a secuirty group for this to allow internal traffic from your VPC CIDR range:
I only want particular people to view them
This is probably a job for authentication on the app, as oppose to security groups, unless your certain of the public IPs from which you wish people to connect.
In the above examples above a Source of 0.0.0.0/0 is allowing traffic from anywhere to reach that port. The console has a convenient dropdown which lets you set My IP if you only want to allow traffic from the IP you're using to connect to the console. Otherwise you'd need to manually calculate the CIDR blocks.
Hope this helps. It probably raises more questions.
Https/Http are important for you. Both are used with websites. Https is http over SSL, meaning more secure than http. You just need these.
Http/https uses TCP port 80 and 443 by default.
SSH is used to securely access a Unix based server.

How can I troubleshoot an AWS Application Load Balancer giving 504, while the EC2 instance behind it gives 200?

I have an EC2 instance with a few applications successfully deployed onto it, listening for connections on ports 3000/3001/3002. I can correctly load a web page from it by connecting to its public DNS or public IP on the given port. I.e. curl http://<ec2-ip-address>:3000 works. So I know that the apps are running, and I know that the port bindings/firewall rules/EC2 security groups are all set up correctly to receive connections from the outside world.
I also have an Application Load Balancer, which is supposed to route traffic to the 3 apps depending on the host name, but it always gives me "504 Gateway Time-out". I've checked all the settings but I can't see what's wrong and I'm not really sure how to troubleshoot it from here.
The ALB has a single HTTPS/443 listener, with a cert that's valid for mydomain.com, app1.mydomain.com, app2.mydomain.com, app2.mydomain.com.
The listener has 3 rules, plus the default rule:
Host == app1.mydomain.com => app1-target-group
Host == app2.mydomain.com => app2-target-group
Host == app3.mydomain.com => app3-target-group
Default action (last resort) => default-target-group
Each target group contains only the single EC2 instance, over HTTP, with the following ports:
app1-target-group: 3000
app2-target-group: 3001
app3-target-group: 3002
default-target-group: 3000
Given that I can access the app directly, I'm sure it must be a problem with the way I've configured the ALB/listener/target groups. But the 504 doesn't give me much to go on.
I've tried to turn on access logs to an S3 bucket, but it doesn't seem to be writing anything there. There's a single object called ELBAccessLogTestFile, and no actual logs in the bucket.
EDIT: Some more information... I actually have nginx installed on the EC2 instance, which is where I was previously doing the SSL termination and hostname-to-port mapping/routing. If I change the default-target-group above to point to port 443 over HTTPS, then it works!
So for some reason, routing traffic
- from the ALB to the EC2 instance over HTTPS on port 443 -> OK!
- from the ALB to the EC2 instance over HTTP on port 3000 -> Broken!
But again, I can hit the instance directly on HTTP/3000 from my laptop.
Communication between resources in the same security group is not open by default. Security group membership alone does not provide special access. You still need to open the ports in the security group to allow other resources in the security group to access those ports. You can specify the security group ID in the rule's source field if you don't want to open it up beyond the resources in the security group.

Access localhost on Google Cloud instance using External IP

There are many similar questions to this on SO, but none of the solutions I saw really solved my issue completely. I'm doing test runs for a website framework hosted on the Google Cloud Platform.
By default, the website is hosted on http://localhost:2800 And I know the external IP of the instance I'm running it on. How can I access the hosted website through a browser on my local machine? Do I use virtual hosts / port forwarding etc.?
go to your VPC firewall
https://console.cloud.google.com/networking/firewalls
and create a firewall rule to allow traffic on your desired tcp port
Create a Firewall Rule for SQL Server
Configure a firewall rule to allow traffic on port 1433 so other clients can connect to the newly created SQL Server instance over the public internet:
In the Developers Console main menu, go to the Firewall rules section.
OPEN THE FIREWALL RULES
Click the Add firewall rule button.
Name the new firewall rule allow-tcp-1433.
Set Source Filter to IP Ranges.
For Source IP Ranges enter 0.0.0.0/0. This value allows access by all IP addresses.
Warning: This configuration leaves your SQL Server instance open to traffic from everyone, everywhere. It is used only for demonstration purposes. In production environments, restrict access to only those IP addresses that need access.
For Allowed protocols and ports enter tcp:1433.
Click the Create button to create the firewall rule.
Set firewall rules for you google cloud project with following properties:
Target: all instances
Direction: ingress
Source IP ranges: 0.0.0.0/0
Ports and protocols: allow all
Then Depending on your framework, set allowed_host to externalIP or "*" .
For example - In Django, in settings.py set ALLOWED_HOSTS = ["*"]
Now run server on specific 0.0.0.0:[your_port]
For example in django - Python manage.py runserver 0.0.0.0:8000
After this note down you instance external IP address and then in your browser :- goto
[external-IP:[your_port]]
you have to go VPC network, then add firewall to allow your port. then don't forget to select [All intances in the network] (see pic). because, by default its value is [Spesified by tags].
and you can access that instance to its External IP
Try your [externalip]:[port] This worked for me in Amazom ec2.
example: 31.181.171.141:2800