I've set up a VM and am trying to use a Python script to send IPv6 messages to my computer so I can analyze it using WireShark. The host computer is Windows, and I want to see messages from a Linux VM. However, when I try to send messages, socket.bind() returns with an invalid argument error. What IPv6 address should I use as the local IP for binding sockets? I'm 99% sure that the error is coming from binding to an invalid IP. So what should I use as the IP? Here is the output of nmcli dev show, hopefully this is enough information to help me figure this out. If it's not, let me know and I'll add more info.
[eng#peter test_scripts]$ nmcli dev show
GENERAL.DEVICE: enp0s3
GENERAL.TYPE: ethernet
GENERAL.HWADDR: 08:00:27:F7:9A:17
GENERAL.MTU: 1500
GENERAL.STATE: 100 (connected)
GENERAL.CONNECTION: System enp0s3
GENERAL.CON-PATH: /org/freedesktop/NetworkManager/ActiveConnection/0
WIRED-PROPERTIES.CARRIER: on
IP4.ADDRESS[1]: 10.0.2.15/24
IP4.GATEWAY: 10.0.2.2
IP4.DNS[1]: 10.0.2.3
IP4.DOMAIN[1]: stc.syrres.com
IP6.ADDRESS[1]: fe80::a00:27ff:fef7:9a17/64
IP6.GATEWAY:
GENERAL.DEVICE: lo
GENERAL.TYPE: loopback
GENERAL.HWADDR: 00:00:00:00:00:00
GENERAL.MTU: 65536
GENERAL.STATE: 10 (unmanaged)
GENERAL.CONNECTION: --
GENERAL.CON-PATH: --
IP4.ADDRESS[1]: 127.0.0.1/8
IP4.GATEWAY:
IP6.ADDRESS[1]: ::1/128
IP6.GATEWAY:
I've tested 'fe80::a00:27ff:fef7:9a17/64', 'fe80::a00:27ff:fef7:9a17' and others, but still can't get it to bind. What IPv6 address should I use?
If you want to listen, your best bet is to bind to :: which is the equivalent of binding to 0.0.0.0.
If you want to connect to that server, keep in mind you are using link-local addresses, which require a scope ID in order to function properly.
For example, on Linux, to connect to host fe80::1 on interface eth0 you would connect to fe80::1%eth0. If you're dealing with the socket module, don't forget to either use getaddrinfo() or be very careful to populate scopeid.
Related
I'll try be concise, but please let me know if I can provide any more helpful pieces of information.
I have client and server Python programs, and they work fine when ran on the same machine, and when the client connects to my machine's local IP (not 127.0.0.1, but the IP assigned to my machine). I have not been able to get this to work with my public IP.
I get a [Errno 61] Connection refused error when I try to get the client to connect to my router's public IP address. My server binds to all interfaces using bind(("0.0.0.0", 50000)), and I already set up port forwarding for my router. I verified that the program is listening on that port by running netstat -an | grep LISTEN and finding the following line:
tcp4 0 0 *.50000 *.* LISTEN
I can also seemingly reach the port through an online port checking tool, which shows that the port is open when I am running my program, and closed when I close that program. My program also registers the connection from this tool.
The fact that my program accepts the connection from the port checking tool gives me the impression that my client code is missing something, but I can't find any answers. It might be worth noting that I am still running my server and client code on the same machine, but I'm not sure why that would derail things. Here's the code I use to connect on the client side:
tcp_client = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
tcp_client.connect(('my_public_ip', 50000))
Are there any diagnostic steps that I can follow to narrow down my issue?
Before you spend any more time on this, try connecting to your public ip from a computer outside your home network. Spend a couple of dollars on an AWS instance for an hour if you have to, or try connecting from a friend's machine, whatever. It will probably work just fine.
I suspect the problem is simply that you cannot, from inside your home network, connect to your router's public ip address. I tried the same thing with my local network and ran into the same behavior.
If you really need to your public ip during development, you can just assign that as an alias to one of your local interfaces (ip addr add 1.2.3.4/32 dev eth0)...but it's probably easier just to use your an address on your local network, or just arrange for regular access to a remote system for testing.
In Python when we want to make a script that listens for multicast traffic we set the IP_ADD_MEMBERSHIP option of the socket with a value that consists of the multicast group address and the address of a local interface on which it will listen for the group's traffic.
Many examples on the Internet pass to IP_ADD_MEMBERSHIP the INADDR_ANY wildcard address as the local interface, and some of them state that this will make the socket to listen on all interfaces for multicast packets. However the Linux ip(7) man page states that when using INADDR_ANY
"an appropriate interface is chosen by the system"
and the freebsd man page says that it will choose the "default interface".
So either some answers online are wrong, or there's something that I'm missing here. I believe there's a confusion with INADDR_ANY when used as a parameter in IP_ADD_MEMBERSHIP, and INADDR_ANY when used as a parameter in bind() (represented by an empty string) but I'm not really sure. Can someone please clarify what is happening with INADDR_ANY or 0.0.0.0 when used in IP_ADD_MEMBERSHIP (i.e. it chooses the default interface or all interfaces) and if it behaves differently when used with bind?
When INADDR_ANY is given as the address in a bind call, this causes the socket to listen on the given port for any network interface.
After calling bind in this way, you'll see an entry like this in the output of the netstat command:
udp 0 0 0.0.0.0:46162 0.0.0.0:*
This is a UDP socket that was bound to INADDR_ANY with port 46162.
When used as the interface address when setting the IP_ADD_MEMBERSHIP option, INADDR_ANY indicates that the OS will chose an interface to join the given multicast group on, i.e. the "default" network interface.
It does not mean that it will join the group on all interfaces. To do that, you would need to itereate over all network interfaces and set the IP_ADD_MEMBERSHIP option on each one.
I've worked with Linux, Solaris, FreeBSD, and Windows, and none of them joins a multicast group on all interfaces when using INADDR_ANY.
I am trying to send some traffic via python using scapy (on Ubuntu). I am using a range of source IPs (10.0.0.32/29). Everything seems to be working (at least I see the traffic in wireshark and it reaches my firewall) but I am having a problem completing the TCP handshake using the IP addresses that aren't the main IP of the eth0 adapter. Does anyone know if this is possible to do:
Source:
from scapy.all import *
import random
sp=random.randint(1024,65535)
ip=IP(src="10.0.0.234/29",dst="www.google.com")
SYN=TCP(sport=sp, dport=80,flags="S",seq=10)
SYNACK=sr1(ip/SYN)
my_ack=SYNACK.seq+1
ACK=TCP(sport=sp,dport=80,flags="A",seq=11,ack=my_ack)
send(ip/ACK)
payload="SEND TCP"
PUSH=TCP(sport=sp,dport=80,flags="PA",seq=11,ack=my_ack)
send(ip/PUSH/payload)
Because you are behind a NAT/router, you should check it allows you to use the full range of IPs. If it is running DHCP protocol, your eth0 will typically recieve a unique IP adress that will be the only routed in your private network.
Furthermore, you must ensure your kernel knows what IPs are attributed to it, else it will drop response packets. If you want to use the full range of IP, you have two choices :
Create virtual devices with virtual mac adresses, each requesting an IP through DHCP.
Configure your router so it statically routes the full IP table to your host, and alias each IP you intend to use
Once you have done that, there is no reason you wouldn't be able to syn/ack from your multiple source IPs. From distant server point of view, there wouldn't be any difference between what you are trying to do and several machines in a local network requesting a page at the same time.
I'm trying to learn how to directly (no libraries) send DHCP request from python on multi-homed machine (multiple interfaces).
I've looked at pydhcplib, but still do not get it.
This code send DHCP packet on specific interface (eth3 in my case - no IP assigned), but it sends with eth0 IP address. How to change my src IP to 0.0.0.0?
dhcp-message is truncated in this example
LOCAL_PORT=68
SERVER_PORT=67
LOCAL_IP="0.0.0.0"
BCAST_IP="255.255.255.255"
LISTEN_DEV="eth3"
MSG_SIZE=2048
Conn=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Conn.settimeout(5)
Conn.setsockopt(socket.SOL_SOCKET,IN.SO_BINDTODEVICE,LISTEN_DEV+'\0')
Conn.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
Conn.bind((LOCAL_IP, LOCAL_PORT))
# Create DHCP-Discovery
msg="010106003f7d1664......"
Conn.sendto(msg.decode("hex"),(BCAST_IP,SERVER_PORT))
received = Conn.recv(MSG_SIZE)
Conn.close()
I assume you already know about the Advanced Interprocess Communication Tutorial.
Spoiler Alert: If you want to jump straight to the bottom line, have a look at the DHCP Query recipe.
Edit:
The special value INADDR_ANY (0.0.0.0, or the empty string '' in a python socket) is not an IP address.
"When an address is specified as INADDR_ANY (a manifest constant
defined in < netinet/in.h >), the system interprets the address as 'any
valid address'."
From RFC 2131:
In the case of a client using DHCP for initial configuration
(before the client's TCP/IP software has been completely
configured), DHCP requires creative use of the client's TCP/IP
software and liberal interpretation of RFC 1122. The TCP/IP
software SHOULD accept and forward to the IP layer any IP packets
delivered to the client's hardware address before the IP address is
configured; DHCP servers and BOOTP relay agents may not be able to
deliver DHCP messages to clients that cannot accept hardware
unicast datagrams before the TCP/IP software is configured.
Presumably you're running this program on a system where the ethernet interfaces have already been configured and have valid IP addresses. I'm not sure why you'd want the source IP address to be 0.0.0.0, but perhaps you could set the interface IP to 0.0.0.0 with ifconfig to get the effect you want.
Or you could use a RAW socket and build the IP and UDP headers yourself to contain anything.
How can I check if a specific ip address or proxy is alive or dead
Because there may be any level of filtering or translation between you and the remote host, the only way to determine whether you can connect to a specific host is to actually try to connect. If the connection succeeds, then you can, else you can't.
Pinging isn't sufficient because ICMP ECHO requests may be blocked yet TCP connections might go through fine.
Maybe this question here will help, its about pinging in python.
Post
An IP address corresponds to a device. You can't "connect" to a device in the general sense. You can connect to services on the device identified by ports. So, you find the ip address and port of the proxy server you're interested in and then try connecting to it using a simple socket.connect. If it connects fine, you can alteast be sure that something is running on that port of that ip address. Then you go ahead and use it and if things are not as you expect, you can make further decisions.