Python, Flask client ip address - python

I need to log the IP address of every user of my webapp, that I've created with Python and Flask.
I'm using
request.remote_addr
But that's return the IP address of the server the app is deployed to. Any fixes to this?

How do you deploy the flask application?
I guess you deploy your app via a reverse-proxy server like nginx, right?
If you did that then request.remote_addr is the address of your server because your server sent client's request to your application and sent the response to the client.
To fix this, see: http://flask.pocoo.org/docs/0.11/deploying/wsgi-standalone/#proxy-setups

The easiest way to get the user's(also known as client) IP is to set this as a variable or use it directly.
request.environ['REMOTE_ADDR']
To get your server's IP:
request.remote_addr

Related

Accessing locally hosted site through public ip

I have setup a django app on a apache server in a VM. The site is accessible when I use the apache server IP in the VM browser. It is also accessible from the host browser through it's local IP. But, I cannot access it through the public IP over the internet. I get a site can't be reached error
I have set up port forwarding such that:
1. All router requests on port 80 are forwarded to local IP
2. All requests to local IP on port 80 are forwarded to the VM
I checked if my port is open on my public ip using http://www.yougetsignal.com/tools/open-ports/
It says that my port is closed. Same results with http://canyouseeme.org/
I am able to ping my public ip successfully.
I have tried disabling all my firewalls but this has not helped. Please tell me if you need any code to be shared. Any help would be appreciated.
Edit:
Extra information: It seems my router's WAN IP is different from my public IP. I can access the site through the WAN IP from the host browser but again, I am not able to access it over the internet.
You just need a public IP address or push your application to the hosting (like this for example https://gpdhost.com/offers/).
ToDo: learn DMZ, learn WAN-LAN packet forwarding process, learn TCP/IP routing, learn public and private IP addressing and learn NAT.
Description: http/https connection conversation (client-outside vs your-server):
1) client: in browser write: sharan-site/;
2) get IP by DNS name from public servers? But public servers don't know your ip:dns-name pair...
=> fail
next example:
1) client: 192.168.1.1/ - where IP is your server
2) so where is it?
=> nowhere, it is private IP address! Fail...
Desc+: Port forwarding it is NAT feature. Your router must have public IP address, and you must setup DMZ like scheme in your local network: https://www.cisco.com/c/en/us/support/docs/ip/network-address-translation-nat/13772-12.html
Desc++: that sites check outside tcp/80 port on your router and PC, and it's open, no questions... But this no help for your task.

Flask server not visible from my public ip address

I'm trying to run a flask server on my desktop PC that is publicly available on the internet. I've done the following:
Set up a static IP address: 192.168.1.11 (http://i.imgur.com/Z9GEBYV.png)
Forwarded port 33 on my router to my static ip address (http://i.imgur.com/KGNQ2Qk.png)
Setup flask to use my static ip and port: 33
I'm using the following code as a test webserver
from flask import Flask, request, redirect
app = Flask(__name__)
#app.route("/")
def hello_world():
return "Test 123 "
if __name__ == "__main__":
app.run(host="0.0.0.0", port="33")
When I open my browser to: http://192.168.1.11:33/ the page displays properly, I see "Test 123"
My problem comes when trying to connect to my webserver from my public ip address When I open my browser to http://xx.xxx.xxx.xx:30 (my ip address) all I see is "this site can't be reached, xx.xxx.xxx.xx refused to connect"
I've looked up all the stack overflow answers, I've done the following:
Turned off windows firewall
Changed host from "192.168.1.11" to "0.0.0.0"
Tried a different port
screenshot of code running and error shown: http://i.imgur.com/a05GvEs.png
My question is: What do I need to do to make my flask server visible from my public ip address?
Do you have DHCP activated on your router?
If yes do you see your host as 192.168.1.11 in there?
You have to use '0.0.0.0' on host, that tells Flask to listen on all addresses.
Try specifying the port with quotes as app.run(host="0.0.0.0", port="33")
change it to app.run(host= '0.0.0.0', port="33") to run on your machines IP address.
Documented on the Flask site under "Externally Visible Server" on the Quickstart page:
http://flask.pocoo.org/docs/0.10/quickstart/#a-minimal-application
Add port forwarding to port 33 in your router
Port forwarding explained here
http://www.howtogeek.com/66214/how-to-forward-ports-on-your-router/
You must give the public ip address/LAN ip address as an argument to app.run method.
When you don't provide host argument, it works fine with http://localhost:8888/ and http://127.0.0.1:888/, but not to access outside the system where you are running the REST services
Following is the example.
app.run(host="192.168.0.29",debug=True, port=8888)
You must try and use the same ip of the development server. Thus, for instance, if the dev server is running on a PC with the address 192.168.1.11
and port 33, other clients must point at the same address: 192.168.1.11:33.
As far as my small experience, it works with the debugger disabled, but I did not check if this is an essential prerequisite.
good luck
Every webservice should be run from different port address.Single service is running from a single port.

How to get CherryPy to listen only on a specific host

I have a flask app that I want to deploy using CherryPy's built in server. I chose CherryPy so that the app can be deployed without having to reverse proxy (ie. nginx in front).
I'm having trouble getting CherryPy to listen for requests on just a single hostname.
Say I'm serving 2 sites: test1.com and test2.com (and have them set in my hosts file to point back to localhost).
My /etc/hosts file:
127.0.0.1 test1.com test2.com
CherryPy is serving test1.com, test2.com doesn't have anything serving it.
My cherrypy file is as follows:
import cherrypy
from my_test_flask_app import app
if __name__ == '__main__':
cherrypy.tree.graft(app, "/")
cherrypy.server.unsubscribe()
server = cherrypy._cpserver.Server()
server.socket_host = "test1.com"
server.socket_port = 8030
server.thread_pool = 30
server.subscribe()
cherrypy.engine.start()
cherrypy.engine.block()
Set up this way, I go to test1.com:8030 on my browser and it works as expected.
But when I go to test2.com:8030, the same app is served. I expected it not to serve anything, since CherryPy isn't set up to listen for test2.com.
To me, it seems that CherryPy is just listening for everything on the given port (8030), and treating the socket_host part as if its 0.0.0.0
Am I missing something here? I've looked through lots of docs and tutorials, but all things suggest that this code snippet should be working as I expected.
Thanks
Here's how you can setup what you want...
root = Root()
RootApp = cherrypy.Application(root)
Domain2App = cherrypy.Application(root)
SecureApp = cherrypy.Application(Secure())
vhost = cherrypy._cpwsgi.VirtualHost(RootApp,
domains={'www.domain2.example': Domain2App,
'www.domain2.example:443': SecureApp,
})
cherrypy.tree.graft(vhost)
https://cherrypy.readthedocs.org/en/3.3.0/refman/_cpwsgi.html#classes
Hope this helps!
You misunderstand the socket listen address - they are IP addresses only, not on DNS names. Set this way, CherryPy listens to the localhost (127.0.0.1) only - try using your Ethernet/Wlan local address and you should get connection refused.
Also, you can wrap your application with a WSGI middleware that checks the Host header for the proper domain, or use CherryPy virtual host facility to check the host header.

When to use route_url or route_path in Pyramid?

I have an issue with route_url and my setup. On the server I have a paster server which listen on 127.0.0.1 on port 6543 and a nginx server which does reverse proxying from port 80 to port 6543.
I'm also using paste prefix to retrieve the real client IP with this setup in my ini file:
[filter:paste_prefix]
use = egg:PasteDeploy#prefix
[pipeline:main]
pipeline =
paste_prefix
myapp
The server is on a private LAN and I'm trying to connect to the server through a SSH tunnel set up as this:
ssh me#sshgateway -L 8080:nginx_server_ip:80
And I connect to the web page on my client at this url: http://localhost:8080
The main page is displayed correctly but then all links generated with request.route_url are redirecting to localhost/url (without the :8080).
I guess this have something to do either with nginx or paste prefix (or both).
I hope that replacing route_url with route_path will probably solve this problem without fixing the nginx/ini setup issue.
Is there any reason to call route_url instead of route_path, ever ?
route_url is useful in situations like generating a redirect from HTTP to HTTPS, or to a different subdomain. Other than that route_path is probably preferable.

How to get client IP address using python bottle framework

I need client IP address using python. I have tried below code but its not working in server:
from socket import gethostname, gethostbyname
ip = gethostbyname(gethostname())
print ip
On the server, I get '127.0.0.1' every time. Is there any way to find IP address of the client?
You're getting the IP address of your server, not of your server's clients.
You want to look at the request's REMOTE_ADDR, like this:
from bottle import Bottle, request
app = Bottle()
#app.route('/hello')
def hello():
client_ip = request.environ.get('REMOTE_ADDR')
return ['Your IP is: {}\n'.format(client_ip)]
app.run(host='0.0.0.0', port=8080)
EDIT #1: Some folks have observed that, for them, the value of REMOTE_ADDR is always the same IP address (usually 127.0.0.1). This is because they're behind a proxy (or load balancer). In this case, the client's original IP address is typically stored in header HTTP_X_FORWARDED_FOR. The following code will work in either case:
#app.route('/hello')
def hello():
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR') or request.environ.get('REMOTE_ADDR')
return ['Your IP is: {}\n'.format(client_ip)]
EDIT #2: Thanks to #ArtOfWarfare's comment, I learned that REMOTE_ADDR is not required per PEP-333. Couple of observations:
The CGI spec does require REMOTE_ADDR:
The REMOTE_ADDR variable MUST be set to the network address of the client sending the request to the server.
However, PEP-333 does not explicitly require HTTP_REMOTE_ADDR, only going as far as this (emphasis mine):
A server or gateway SHOULD attempt to provide as many other CGI variables as are applicable.
All of the (admittedly few) web frameworks that I'm familiar with set HTTP_REMOTE_ADDR. AFAICT, it's a de facto "standard." But technically, YMMV.
Server might be behind a proxy. Use this for proxy and forward support:
request.environ.get('HTTP_X_FORWARDED_FOR') or request.environ.get('REMOTE_ADDR')
If you're trying to get the external IP, you will need to get it from an external source, i.e whatismyip.com or somewhere that offers an api. If that's what you're looking for, take a look at the Requests module http://docs.python-requests.org/

Categories