When I make request to a url, I believe the ip address of the client is sent to the server. And in that case the ip address must be present in request header, or am I wrong?
So, I say
import requests
resp = requests.get("http://localhost:8000/test")
print resp.request.headers
But I can't see any ip address when printing resp.request.headers, so how can I view the ip address of client. And if I can't see it as part of resp.request.headers, how does server get the ip address of the client if it isn't present in request header?
IP address is not set by client, it is part of the connection. Quote from here:
(remote address) is taken from the ip address that hits the http server and not in
the request. as if you are behind a proxy you would only see the ip of
the proxy. it doesnt touch the http header data
A server gets a connection, natrually it also knows where it comes from.
Related
I have successfully made a DNS request and I send it to my DNS server using UDP sockets in python. Then, I receive the response and convert into a byte-array using python's bytearray() method. But this response contains many jibberish, non-important data in addition to the IP addresses of the canonical server. How should I parse this response to get a result like this :
I am getting the values of the IP address like 74.125.200.106 and all in the response, but how should I extract it from the response bytearray?
I wrote a small script to get the ip address for a list of hostnames. However when I try to ping the ip address I get request time outs. Why can this happen?
import csv
import socket
path = 'Clients.csv'
with open(path) as fopen:
rows = csv.reader(fopen)
for row in rows:
try:
resp = socket.gethostbyname(row[0])
print(row[0], resp)
except:
continue
The answer is in the question: the DNS server you are requesting knows about the name, so it gives you the matching IP.
It does not mean that the machine that does the ping can actually find a network path to ping the destination. For example, there could be a firewall between the originated server and the pinged server, networks between source and destination are not necessarily routed together, etc.
Timeouts are probably the sign of a blocking firewall.
I have some code that hosts a local server and when a user connects it will send them some html code, which works fine.
But I want it so if they connect to http://localhost:90/abc it will show something different. How can I get the exact url they connected to?
Here is my code:
import socket
sock = socket.socket()
sock.bind(('', 90))
sock.listen(5)
print("Listening...")
while True:
client, address = sock.accept()
print("Connection recieved: ", address)
print(The exact url they connected to.)
print()
client.send(b'HTTP/1.0 200 OK\r\n')
client.send(b"Content-Type: text/html\r\n\r\n")
client.send(b'<html><body><h1>Hello, User!</body></html>')
client.close()
sock.close()
I tried print(client.getpeername()[1]), but that gets the client ip, and if there is a similar way to get the ip they connected to it probably wont get the 'abc' part of the url.
Thanks in advance.
Socket's don't have a notion of URL, that's specific to the HTTP protocol which runs on top of a socket. For this reason, only part of the HTTP URL is even used in the creation of a socket.
|--1---|----2----|-3-|--4-|
http:// localhost :90 /abc
Specifies which protocol inside of TCP the URL uses
Specifies the remote host, either by IP address or hostname
Specifies the remote port and is optional
Specifies the path of the URL
Only parts 2 and 3 are actually known to a TCP socket though! This is because TCP is a very basic form of communication, HTTP adds a bunch of functionality on top of it like requests and responses and paths and so on.
Basically if you're implementing an HTTP server, knowing the /abc part is your job. Take a look at this example. The client actually sends the /abc part to the server, otherwise it has no way of knowing which path the request is for.
When the client connects to your server, it will send:
GET /abc HTTP/1.1
Host: localhost
more headers...
<blank line>
Your server needs to parse the GET line and extract /abc from that.
The server has a public IP, the client is behind a nat.
How could the client communicate with server by udp in qt?
The client will send some data to server first, then how could server reply to client?
The current code is this:
server:
self.udpSocketGet = QtNetwork.QUdpSocket()
self.udpSocketGet.bind(QtNetwork.QHostAddress.LocalHost, serverPort)
self.udpSocketGet.readyRead.connect(self.receive)
def receive(self):
while self.udpSocketGet.hasPendingDatagrams():
size = self.udpSocketGet.pendingDatagramSize()
if size > 0:
data, senderAddr, senderPort = self.udpSocketGet.readDatagram(size)
client:
def sentToServer(self,data):
udpSocketSend = QtNetwork.QUdpSocket()
udpSocketSend.writeDatagram(data.encode('utf-8'), serverAddress, serverPort)
The answer to your question goes beyond qt. Check out http://en.m.wikipedia.org/wiki/UDP_hole_punching and http://en.m.wikipedia.org/wiki/NAT_traversal
I am editing this answer after I looked back and found out that the server has a public IP address. In that case, the server will just have to respond to whatever IP address the request comes from. In case the client is communicating via NAT, the server will see the public address of the router and will be totally unaware that the actual client is behind that router.
Read Receiving a response through UDP
The bottom line is that you either have to use port mapping or UPNP.
See also https://superuser.com/questions/456812/nat-and-udp-replies
Again, the server code should not be concerned with NAT traversal. Either the client uses UPNP and the router has UPNP enabled. Or the router is configured to port forward or remember the source and destination IP addresses and ports of the packet originating from the client and properly farwards back the packets sent by the server.
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/