Connecting to BACnet device giving single use socket address error - python

I've tried to look through posts to see if i could find anything but haven't managed to find it yet.
I'm running the SCADA BACnet device simulator on my localhost.I'm assuming the ip for the device is my localhost ip since the only IP i could find was in the deviceAddressBinding property which showed 192.168.x.xx
I am running through the bacpypes(python library for bacnet) tutorial for the SampleApplication and when I first tried running the tutorial, it stated that my .ini file ip is not a valid address in the context. So I tried to put in the simulator's settings to try and connect to the simulator and now it's giving me a Only one usage of each socket address (protocol/network address/port) is normally permitted error. Not quite sure where to go from here, am I perhaps missing something?
my .ini file:
[BACpypes]
objectName: Testing Device
address: 192.168.x.xx #tutorial came with 128.253.109.40/20
objectIdentifier: 123
maxApduLengthAccepted: 1024
segmentationSupported: segmentedBoth
vendorIdentifier: 123
foreignPort: 47808
foreignBBMD: 192.168.1.254
foreignTTL: 30
My simulator properties:

it seems to be a windows issue. Replaced :
this_application = WhoIsIAmApplication(this_device, args.ini.address)
with:
this_application = WhoIsIAmApplication(this_device, ('', 47808))

your sample application and BACnet simulators are opening a server socket. looks like both are using the same port number. you can change the port number in ini file as given below
address: 192.168.1.22:47809
by default the BACPypes sample applications run on the 47808 port number unless you explicitly mention in the configuration file.

Related

Why "[Errno 61] Connection refused" when program is listening on correct port, socket is bound to all interfaces?

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.

Cannot bind to external IP address of google compute engine VM instance

I am trying to test a simple client-server setup between my laptop and my google compute engine instance using python. The setup works fine between 2 laptops. But when I run the server program in my VM instance I get the following error after calling the bind command: "socket.error: [Errno 99] Cannot assign requested address"
I am trying to bind to the external IP address so I can receive data from an external device.
Here is the code snippet
import socket
s = socket.socket()
port = 12345
s.bind(('xxx.xxx.xxx.xxx',port))
Can anyone please tell me why I can't bind to the external IP address. I have tried to find the answer in Google's docs and via online searches but to no avail. I am new to this and don't really even know what info to post that would help in troubleshooting. Thanks in advance.
Here are my firewall rules
Google Cloud's networking has a distinction between internal and external IP addresses. In particular, a GCE VM won't actually have an interface with the externally visible IP address -- the cloud infrastructure handles the translation outside of the instance.
You need to bind to the internal IP address for your instance, and GCP's networking infrastructure will take care of the routing for you, assuming such routing is allowed by your VPC firewall configuration.
Note: As provided, your current firewall configuration does not have a rule that will allow ingress on the 12345 port and you will need to add this and ensure it applies to this particular instance (either via a target tag which is applied to the instance, or by applying the rule to all targets in your network)
You might also consider using 0.0.0.0 (or INADDR_ANY) which in python is just the empty string. So this should also work for you (again, assuming the correct firewall configuration):
import socket
s = socket.socket()
port = 12345
s.bind(('',port))

Are hostnames permanent? Can I change it?

Sorry for the general questions but I am not deep into the subject and the info I am finding in the internet is very confusing to me. I am trying to retrieve data from a sensor that is connected to the wifi, and for it I need to call a function that has this sensor's IP Address as a parameter. Therefore, when the IP Address changes, I need to keep rewriting the IP Address on my script. I have found this way to get the IP Address of the sensor. Assuming my sensor's hostname is "mydevice".
hostname = "mydevice"
ip = socket.gethostbyname(hostname)
I found out the hostname of my sensor using an IP Scanner App on my phone to just get the info of the devices that are on my network. The problem is that if I take the sensor to another place and use another wifi, it doesn't show a hostname in this app anymore. I am very confused and therefore I have the following questions.
I know each device has a hostname. Is this hostname permanent and can it be used in different WiFi networks?
If the hostname is not permanent, can I somehow set it to be permanent?
If I cannot set the hostname permanently, can I somehow include code in my python script so that the ip address of my sensor is retrieved every time the script runs, in case there are any changes?
Thanks so much.

Get IPv4 Address from python, even with vpn on

So I'm using socket to connect clients to the server. For that, I need the computer's ip. Currently, the best way I found is this:
socket.gethostbyname(socket.gethostname())
I then use requests to tell my clients about my ip, and they connect. The issue here is that when my vpn is on, I get another host and that causes the clients to be unable to connect.
But when I open command prompt and type ipconfig, I get the correct ip regardless of the vpn status. So I need to get the same ip as would be shown under IPv4 in command prompt, is this possible in python?
I'm trying to get the server to work on any device regardless of exceptions such as this.
Thanks!
The way you retrieve the IP addresses of your system (most systems these days have multiple) uses the hostname of your system and therefore depends on i.e. DNS and your local hosts file. It will only give you one address, and can be quite unreliable, as you have seen with your VPN.
I'd recommend using the netifaces package. With it you can retrieve a list of all network interfaces and all their addresses.
An example from the manual:
>>> addrs = netifaces.ifaddresses('en0')
>>> addrs[netifaces.AF_INET]
[{'broadcast': '10.15.255.255', 'netmask': '255.240.0.0', 'addr': '10.0.1.4'}, {'broadcast': '192.168.0.255', 'addr': '192.168.0.47'}]
You should be able to install it with pip. The source repository is here: https://bitbucket.org/al45tair/netifaces
Yeah so I ran into this issue and it seems that ipconfig command does work, so I used the following. It calls ipconfig using subprocess and uses a regex pattern to match the ipv4 line. Since there's two ipv4 lines, and on my machine the VPN appeared as Unknown adapter WindscribeWireguard: before Wireless LAN adapter Wi-Fi: so I ended up matching the last one that appears. It's possible this isn't robust but I'm sure one of my users will let me know then.
from subprocess import check_output
import re
ipv4_pattern = re.compile(r'IPv4 Address.*:\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
def get_ipv4():
ipconfig_output = check_output(['ipconfig'], shell=True, text=True, encoding='iso8859-2')
return ipv4_pattern.findall(ipconfig_output)[-1]

IPv6 Address to supply for Python socket source

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.

Categories