python bind socket.error: [Errno 13] Permission denied
Asked Answered
M

4

32

I have a python script which gets packets from a remote machine and writes them (os.write(self.tun_fd.fileno(), ''.join(packet))) to a tun interface gr3:

Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
inet addr:10.0.0.6  P-t-P:10.0.0.8  Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
RX packets:61 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500 
RX bytes:5124 (5.0 KiB)  TX bytes:0 (0.0 b)

I would like to receive those packets via a separate pong script as follows:

import threading, os, sys, fcntl, struct, socket
from fcntl import ioctl
from packet import Packet

HOST = '10.0.0.6'
PORT = 111
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
    data = conn.recv(1024)
    if not data: break
    else: print data    
    conn.sendall(data)
conn.close()

I got this error :

s.bind((HOST, PORT))
File "<string>", line 1, in bind
socket.error: [Errno 13] Permission denied
Milone answered 2/6, 2014 at 18:40 Comment(3)
What's your question? This seems all normal and expected ... what do you want to know? (111 is a privileged port.)Funicular
I think that's a perfectly good question, with the whole code and error message. Just there's something he/she don't know. If we assumed OP should know everything, there'd be no SO.Lugo
I would like to know on which port my python is writing to the gr3 tun interface in order to listen to it using pong script. os.write(self.tun_fd.fileno(), ''.join(packet)) does not specify the portMilone
L
85

You can't bind to port numbers lower than 1024 as a unprivileged user.

So you should either:

  • Use a port number larger than 1024 (recommended)
  • Or run the script as a privileged user

Harder, but more secure solution if it's really necessary to accept from 111:

  • Run the as unprivileged on a higher port, and forward port 111 to it externally.
Lugo answered 2/6, 2014 at 18:43 Comment(3)
Thank you utdemir but how can I know on what port my script is sending those packets because I know he is writing to the tun interface gr3 but on which port I don't know.Milone
Actually, I don't know how to use tun interface, this is just the answer and the solution for the error coming from s.bind.Lugo
if you're using a Linux server simply put sudo before the commandHaun
A
1

Although not in the original question, just want to expand this to the case of unix sockets for local interprocess communication, i.e. AF_UNIX. As seen in man unix 7:

In the Linux implementation, pathname sockets honor the permissions of the directory they are in. Creation of a new socket fails if the process does not have write and search (execute) permission on the directory in which the socket is created.

On Linux, connecting to a stream socket object requires write permission on that socket; sending a datagram to a datagram socket likewise requires write permission on that socket. POSIX does not make any statement about the effect of the permissions on a socket file, and on some systems (e.g., older BSDs), the socket permissions are ignored. Portable programs should not rely on this feature for security.

So look at the permissions on the socket directory if getting a PermissionError: [Errno 13] Permission denied on bind() for unix sockets.

Abeyance answered 21/9, 2020 at 13:53 Comment(0)
G
0

For anyone else that came to this page for the same error:

Your server may not be running with root privileges. All ports under 1024 are system reserved. You'll need help from a server with root privileges.

For my specific scenario what worked was to setup a reverse proxy with Nginx to my application on a higher numbered port.

In my case the production server I had deployed: Waitress didn't run as root and so didn't support opening ports on the system reserved ports. Launching Nginx to handle SSL encryption and passing all https requests to the application port via http was what worked for me.

I would first make sure that nothing else is using the port you are trying to use and if its clear then make sure your deployed server is setup to handle that port.

This was the documentation I found that explained the situation clearly to me after a lot of hair pulling:

Binding Externally

Waitress should not be run as root because it would cause your application code to run as root, which is not secure. However, this means it will not be possible to bind to port 80 or 443. Instead, a reverse proxy such as nginx or Apache httpd should be used in front of Waitress.

You can bind to all external IPs on a non-privileged port by not specifying the --host option. Don’t do this when using a revers proxy setup, otherwise it will be possible to bypass the proxy.

0.0.0.0 is not a valid address to navigate to, you’d use a specific IP address in your browser.

src= https://flask.palletsprojects.com/en/2.2.x/deploying/waitress/

Gabbie answered 9/1, 2023 at 23:46 Comment(0)
A
0

You might be using a port which is used by another service, or the port might be reserved. Change the port number to a free port, or one you know that isn't in use.

Availability answered 23/7, 2023 at 11:44 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Needlecraft

© 2022 - 2024 — McMap. All rights reserved.