Get Ethernet adapter IPv4 address without using external libraries - python

I have 2 computers connected with crossover cable and first time I need to start PC1 as server and PC2 as client and then second time PC2 as server and PC1 as client. I use UDP socket and it is on Windows. So I cant just put IP in code, I need the server code to get the IP automatically.
I tried this:
hostname = socket.gethostname()
IPAddr = socket.gethostbyname(hostname)
But this gives me wrong IP. I need the IP address that I see when I check Ethernet adapter Ethernet in ipconfig/all.
I'm not sure if you understand me sorry. English is not my best skill.

You could try using the netifaces package. Docs are here.
import netifaces
ip = netifaces.ifaddresses('eth0')[netifaces.AF_INET][0]['addr']
print(ip)
eth0 is just an example, you can get the actual interface name from ipconfig

Related

How can I create a TCP connection in Python between 2 PCs

So far I have made a VERY basic client/server application that creates a TCP connection. I have a lot of programming experience, just never did this low-level stuff and especially nothing with networks. Note that all the prints are just to help me figuring out what is going on. One of the known issues is that jsonip sometimes gives me an IPv4 and sometimes v6, I don't know why but that doesn't matter for now, just to warn anyone who wants to recreate my code.
Server:
import socket
import requests
port = int(input("Enter port you want to open:\n"))
#todo: add errorhandling
print("Adding socket...")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
hostname = socket.gethostname()
print(f"Hostname: {hostname}")
ip_address = socket.gethostbyname(hostname)
print(f"Host address: {ip_address}")
r = requests.get(r'http://jsonip.com')
public_ip_address = r.json()['ip']
s.bind((ip_address, port))
print("Is open for connections on IP: "+public_ip_address+" and Port: "+str(port))
s.listen(5)
print("Done initialisation, listening for incoming connections...")
while True:
clientsocket, address = s.accept()
print(f"Connection from {address} has been established")
clientsocket.send(bytes(f"You have connected to server: {hostname}", "utf-8"))
Client:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ip = input("Enter IP to connect to:\n")
port = int(input("Enter Port to connect to:\n"))
print(f"Connecting to server {ip} ...")
s.connect((ip, port))
msg = s.recv(1024)
print(msg.decode("utf-8"))
On my local machine: Open 20000 in my server.py, it tells me the host is 127.0.1.1, I then enter 127.0.1.1 into my client script and 20000, and they connect. So the Socket has been bound with the 127.0.1.1. (Side question: What is this IP address, is it like the internal IP address of processes in my PC or something? If running ip a on my other machine it is the first one shown of 2)
Using Virtmanager on my machine and running one Linux Server (command line only) and one normal Ubuntu, the server tells me the host is, again, 127.0.1.1 which I don't need to enter into the other VM to know it won't work, what does work however, is getting the IP-address of the Server via ip a, which in this case is 192.168.122.37, and when I enter this IP address into the client, it connects. But in the socket here I bind, again, the 127.0.1.1, so is it arbitrary what I put here? What SHOULD I bind here, the public, the weird or the 192. address?
The first thing I could not get to work was using 2 physical devices. When opening a server on my Linux machine, I cannot connect with my windows machine at all, no matter if I use my public, my 127. or my 192. IP-address. Now my end goal is doing this over the internet so I am walking myself up, describing here the steps I took to try and get where I want to be but here I hit a brick wall where I don't know what is wrong. Am I binding the wrong address on the server, is my router being a problem, is there something else wrong?
I also tried leaving my network using my friends pc a few countries over, but this also just results in a timeout (my theory is that the Router port he is trying to open is closed and I have now idea how I can make the router send data to his PC, which should be not impossible as firefox and every application using internet does it without me having to manually forward every port, I just don't know how). This is my end goal, creating a connection between my friends PC and mine, and this is how far I got (I wouldn't mind skipping the local network if it is not relevant for fixing the global connection problem), so, tl;dr: what did i do wrong, what do i need to bind and what do i need to do for the final result to work?
There are many questions to answer.
Addresses 127.X.X.X are reserved for the loopback interface, most common one is 127.0.0.1. The loopback is a virtual, but important interface and as you have probably guessed, it is usable on the local machine only. You cannot use 127.X.X.X address to make two hosts to communicate with each other.
Addresses 192.168.X.X (and also 10.X.X.X and 172.16-31.X.X.) are reserved for local LANs. They are not valid on the Internet.
You cannot use these addresses to make two hosts to communicate with each other over the public Internet (unless you create a tunnel, an advanced networking topic)
Almost everybody uses them, because we ran out of IPv4 addresses long time ago, they were difficult to get, expensive, etc. Also such hosts are isolated from the Internet, they can be reached only via a router that translates addresses. Such router feature is called NAT. A typical router has one valid Internet address and all connections to the Internet appear as coming from the router. If you contant a service like jsonip.com from a PC, you get your router's address, not your PC's address.
See also: Finding local IP addresses using Python's stdlib
To make your program working, make it to accept connections on all interfaces. See the first example in the socket docs. On Linux, use port numbers >= 1024. Ports < 1024 are reserved, not available to regular users.
Final point is that a firewall may prevent connections to your server. It depends on your system and setup.

Python sockets google dns server

I need my own IP in a small script and in order not to hardcode it, I`ve found a piece of code from here(stackoverflow) that works.
This--
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.connect(("8.8.8.8", 80))
print(s.getsockname()[0])
--
What is not clear for me is why it only works on UDP and not TCP? It has something to do with the google dns server? Thanks in advance.
This has nothing to do with Google and nothing to do with DNS.
All what this code does is to "connect" a UDP socket to an external IP, so that the OS kernel figures out which local IP address it needs to use in order to reach this external system. This is no real connection, i.e. there is no traffic involved but the OS kernel is only checking routing tables and local interfaces in order to decide which IP address to use as source in case one would actually use the socket to send data.
One could do the same with TCP. But in this case a real TCP connection would be established which means that actual traffic would be exchanged and that the connect would fail if the external system would not be reachable on this port (i.e. no listener, firewall in between etc).
With UDP instead connect will not produce any traffic and would fail only if no route to the destination IP address could be determined. This also means that an arbitrary external IP address and port could be used, i.e. ('1.1.1.1',11) would work the same as ('8.8.8.8',80).

How to lookup host name from IPv6 address with Python

How do you lookup the local hostname from an IPv6 address in Python?
I'm trying to diagnose network bandwidth hogs, and I'm using Wireshark to find which IPv6 addresses are using the most bandwidth, but it doesn't include any hostsnames, so I'm left with a CSV of IPv6 addresses and total bytes transmitted.
Note, I'm not talking about converting a generic IP to domain, since that only works for DNS, not your local network's hostnames.
The only command line tool I know for doing this is:
sudo nmap -sn 192.168.1.0/24
but that doesn't list IPv6 addresses.
This is what I found looking online, I'm sorry but i think that what you are lookin at isn't possible.
From WireShark Q&A:
What you're looking at are probably neighbor discovery packets, which
are sent to a special multicast address called "solicited node
multicast".
It's basically the replacement mechanism for ARP, which is not used
for IPv6 anymore.
Usually, if you need to find out where something is coming from you
should try to determine the MAC address of the source, and then log in
to your switches to find the port where that MAC address is connected.
There should be a command that will show you the MAC address table of
the switch. If you can find a port where only the MAC address in
question is listed you need to follow the cable from that port to the
device.
If you have more than one MAC address listed for a port it is usually
a connection to another switch. In that case you need to log in to the
switch it connects to and repeat your search.

python public ip with sockets (err:cannot assign requested addr)

After allowing my raspberry pi to access port 9999 of my router socketname.bind(96.231.140.202,9999) in python gives me a cannot assign error
To port forward I used:
myfiosgateway.com/#/firewall/portforward (the same method
worked fo my apache server) and I have verified that 96.231.140.202 is my pub ip
You cannot bind to your public IP. Your router is doing that. You instead want to bind to your private IP and port forward traffic destined to 9999 to your bound IP on your pi, this address will fall into the rfc compliant private IP ranges, so it will most likely be something like 192.168.1.12 or something similar.
For example:
socketname.bind(0.0.0.0,9999) #the use of 0.0.0.0 will automatically find your available interface on that raspberry pi.
If you let me know exactly what socket library youa re using I can craft the exact code.

Python raw socket doesn't see outgoing data

I use the following code to create a raw socket : http://pastebin.com/pmg9iKgG
As you can see, i want :
all TCP received packet send from port 5555 of a server to my PC,
all TCP send packets from my PC to port 5555 of a server.
The problem is : i'm only able to see incoming packets, not outgoing packets. This is quite annoying for a sniffer...
Could you help me with this?
I'm using Anaconda as python distro (3.6, x64), on windows 10. wireless (intel) or ethernet (through USB adapter cause slim laptop).
I've search the internet and i haven't seen any problem like that. Moreover, MSDN says that it should work in both way (outgoing and incoming) : https://msdn.microsoft.com/en-us/library/windows/desktop/ms740548%28v=vs.85%29.aspx
One common use of raw sockets are troubleshooting applications that need to examine IP packets and headers in detail. For example, a raw socket can be used with the SIO_RCVALL IOCTL to enable a socket to receive all IPv4 or IPv6 packets passing through a network interface. For more information, see the SIO_RCVALL reference.
I would appreciate any help with this )))
Just on thing :
i bypass this line of code :
host = socket.gethostbyname(socket.gethostname())
by :
host = "192.168.0.29"
cause it's not the right value (but that's not the problem, moreover the methode socket.getfqdn() does the job, but i didn't updated my script)
EDIT : it was the windows FW that caused this strange behaviour, by deactivating some filter, i was able to see all incoming and outgoing packets.

Categories

Resources