I have an AWS ELB connected with multiple EC2s that are running the AWS Flask server. I am not sure if AWS ELB passes the complete request to EC2 or not. I know we can do the restrictions at ELB level but I want to put restrictions on only one endpoint and verify the hostname of the server who invoked the endpoint in Flask. Is it possible?
-
1Assuming application load balancer, you can enable [proxy protocol](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-proxy-protocol.html).But this gives only IP of the client, not its DNS. The IP is also available from [x-forwarded-for](https://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/how-elastic-load-balancing-works.html#http-headers) header. – Marcin Aug 05 '20 at 12:44
-
Is there any way to verify the SSL certificate? – Sanjay Sharma Aug 05 '20 at 12:47
-
Maybe this doesn't fit you use case, but you could look into using ALB / WAF to enforce restrictions at the load balancer level. – Marcello Romani Aug 08 '20 at 12:29
-
Restrictions at ELB level... it sounds to me like ELB is not the right place to implement any kind of restrictions. Restrictions sound to me as a synonym of Permissions. I'd rather design a solution based on IAM (and maybe API Gateway). If want to keep this simple, have you consider the option of add a parameter/body to your request with the data/info you need at the other end? HTTP does not do what you are needing/expecting. – Teimatini Marin Aug 10 '20 at 22:10
-
@TeimatiniMarínMeza Yeh. That's already there. I want to add additional security as there will be only one specific client (another server) which will access one particular endpoint and I want to restrict other clients to access it. – Sanjay Sharma Aug 11 '20 at 18:45
-
1@SanjaySharma What about something like this https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-resource-policy-whitelist/ ? If your 'another server' is an EC2 instance this would be easy. Just deploy the instance into an specific ip-range. If not in EC2 then you could enable AWS security on the APIGateway instance. Then create a role/user, and ALLOW execute-api:Invoke for you Resource only if called with that specific role/user. Makes sense? – Teimatini Marin Aug 12 '20 at 02:01
-
@TeimatiniMarínMeza thank you so much for your time and help. I had some idea about this and as per your explanation, this seems to be one of the alternative ways of achieving it. – Sanjay Sharma Aug 12 '20 at 10:31
3 Answers
You could try the following:
import socket
from flask import request
@app.route("/your_route", methods=["GET"])
def your_route():
hostname, aliaslist, ipaddrlist = socket.gethostbyaddr(request.remote_addr)
Note that relying on the remote_addr is unreliable, however as this is unrelated to the topic I will refer to this answer which makes use of ProxyFix:
For more information on socket.gethostbyaddr()
please check out: socket.gethostbyaddr()

- 5,437
- 4
- 24
- 38
-
-
1@SanjaySharma according to this you should be able to get/set an alias, how to retrieve the alias is provided in the answer. https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-creating.html#resource-record-sets-elb-dns-name-procedure – alexisdevarennes Aug 12 '20 at 15:56
I suggest you use the decorator pattern for such cases i.e. you add a new config option IP_LIST with some kind of address set divided by comma.
IP_LIST = "127.0.0.1,127.0.0.2,..."
After that add a new decorator function, and decorate any endpoint with the decorator.
def ip_verified(fn):
"""
A custom decorator that checks if a client IP is in the list, otherwise block access.
"""
@wraps(fn)
def decorated_view(*args, **kwargs):
ip_list_str = current_app.config['IP_LIST']
ip_list = ip_list_str.split(",") if ip_list_str else []
if request.headers.getlist("X-Forwarded-For"):
remote_ip = request.headers.getlist("X-Forwarded-For")[0]
else:
remote_ip = request.remote_addr
if remote_ip not in ip_list:
return "Not sufficient privileges", 403
return fn(*args, **kwargs)
return decorated_view
@app.route("/your_route", methods=["GET"])
@ip_verified
def your_route():
...

- 507
- 1
- 7
- 14
One option is to use a Network Load Balancer which preserves the IP address of the client making the request. You can even have the NLB do the TLS termination just like an ELB. An NLB does not alter the data in the network request, with the exception of TLS termination if you choose to use that.

- 2,826
- 1
- 20
- 28