python websocket failure when run in openshift - python

I have a autobahn twisted websocket running in python which is working in a dev vm correctly but I have been unable to get working when the server is running in openshift.
Here is the shortened code which works for me in a vm.
from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory, listenWS
from autobahn.twisted.resource import WebSocketResource
class MyServerProtocol(WebSocketServerProtocol):
def onConnect(self, request):
stuff...
def onOpen(self):
stuff...
def onMessage(self,payload):
stuff...
factory = WebSocketServerFactory(u"ws://0.0.0.0:8080")
factory.protocol = MyServerProtocol
resource = WebSocketResource(factory)
root = File(".")
root.putChild(b"ws", resource)
site = Site(root)
reactor.listenTCP(8080, site)
reactor.run()
The connection part of the client is as follows:
var wsuri;
var hostname = window.document.location.hostname;
wsuri = "ws://" + hostname + ":8080/ws";
if ("WebSocket" in window) {
sock = new WebSocket(wsuri);
} else if ("MozWebSocket" in window) {
sock = new MozWebSocket(wsuri);
} else {
log("Browser does not support WebSocket!");
window.location = "http://autobahn.ws/unsupportedbrowser";
}
The openshift configuration is as follows:
1 pod running with app.py listening on port 8080
tls not enabled
I have a non-tls route 8080 > 8080.
Firefox gives the following message in the console:
Firefox can’t establish a connection to the server at ws://openshiftprovidedurl.net:8080/ws.
when I use wscat to connect to the websocket.
wscat -c ws://openshiftprovidedurl.net/ws
I get the following error:
error: Error: unexpected server response (400)
and the application log in openshift shows the following:
2018-04-03 01:14:24+0000 [-] failing WebSocket opening handshake ('missing port in HTTP Host header 'openshiftprovidedurl.net' and server runs on non-standard port 8080 (wss = False)')
2018-04-03 01:14:24+0000 [-] dropping connection to peer tcp4:173.21.2.1:38940 with abort=False: missing port in HTTP Host header 'openshiftprovidedurl.net' and server runs on non-standard port 8080 (wss = False)
2018-04-03 01:14:24+0000 [-] WebSocket connection closed: connection was closed uncleanly (missing port in HTTP Host header 'openshiftprovidedurl.net' and server runs on non-standard port 8080 (wss = False))
Any assistance would be appreciated!

Graham Dumpleton hit the nail on the head, I modified the code from
factory = WebSocketServerFactory(u"ws://0.0.0.0:8080")
to
factory = WebSocketServerFactory(u"ws://0.0.0.0:8080", externalPort=80)
and it corrected the issue. I had to modify my index to point to the correct websocket but I am now able to connect.
Thanks!

Based on the source code of autobahn-python, you can get that message only in 2 cases.
Here is the implementation:
if not ((self.factory.isSecure and self.factory.externalPort == 443) or (not self.factory.isSecure and self.factory.externalPort == 80)):
return self.failHandshake("missing port in HTTP Host header '%s' and server runs on non-standard port %d (wss = %s)" % (str(self.http_request_host), self.factory.externalPort, self.factory.isSecure))
Because I think you are using Deployment + Service (and maybe Ingress on top of them) for your server, you can bind your server to port 80 instead of 8080 and set that port in Service and in Ingress, if you are using them.

Related

Python on GCE: connection failed because connected host has failed to respond

I've been working on a project that requires a bit of networking between a server (hosted on GCE) and multiple clients. I created a Compute Engine Instance to run a Python script as shown in this video: https://www.youtube.com/watch?v=5OL7fu2R4M8.
Here is my server-side script:
server = socket.gethostbyname(socket.gethostname()) # 10.128.X.XXX which is the Internal IP
print(server)
port = 5555
clients = 0
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((server, port))
s.listen(2)
print("Waiting for connection...")
while True:
conn, addr = s.accept()
print("Connected to: ", addr)
conn.send(str.encode(f"{clients}"))
clients += 1
and here is my client side-script:
class Network:
def __init__(self):
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server = "10.128.0.2"
self.port = 5555
self.addr = (self.server, self.port)
self.id = int(self.connect())
def connect(self):
self.client.connect(self.addr)
return self.client.recv(2048).decode()
network = Network()
print(f"Connected as client {network.id}")
I know this script works because I have tested it with my computer being the server and 1 client, and another computer being the 2nd client. But when I use the GCE as the server, I get this error in the client script:
TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
Could this be because I am using the internal IP address and not the external?
After this, I tried changing the firewall settings (added 'python-socket') of the GCE and this is what they look like:
But the error still persists...
As answered by W_B, I tried to run these commands on my VM and got the following outputs:
From your description it's evident it's the connection problem.
First of all you have to check if the firewall rule you created is still there. If it's "too broad" and allows for very wide access then it might be removed automatically even without you knowing it. It's on you'r screenshot but check it again just to be sure.
If it's there select the protocol you're goint to be using (I assume it's TCP) - some protocols are always blocked by default by GCP (you can't change this) so creating a rule with "any protocol" allowed is risky. Also - put one or two target IP's (not all inside this VPC) - this is not a must but improves security of your network.
Second - make sure port 5555 you're trying to connect to is accessible from other computers. You can scan the target host with nmap -p 5554 put.server.ip.here
You can scan it from the Internet or other VM's in the same VPC network.
You should get something like this:
root#localhost:~$ nmap -p 443 192.168.1.6
Starting Nmap 7.70 ( https://nmap.org ) at 2020-06-25 17:12 UTC
Nmap scan report for 192.168.1.6
Host is up (0.00091s latency).
PORT STATE SERVICE
443/tcp open https
Nmap done: 1 IP address (1 host up) scanned in 0.04 seconds
If you see 5555/tcp filtered freeciv this means that something blocks the port.
Run nmap on the server (I assume you run some version of Linux) and if you don't want to install any non-essencial software you can use sudo netstat -tulpn | grep LISTEN to get a list of open ports (5555 should be on the list).
Also make sure firewall on your server doesn't block this port. You can use iptables for that.

I want to test my api that is running in VM vagrant in host OS using IP adress :

the server is running in VM with vagrant :
vagrant#ubuntu-xenial:/vagrant/email_api$ python3 emailapi.py
Bottle v0.12.17 server starting up (using WSGIRefServer())...
Listening on http://127.0.0.1:8080/
Hit Ctrl-C to quit.
but when i use IP to access to api i get :
Could not get any response
There was an error connecting to .
Why this might have happened:
-The server couldn't send a response:
Ensure that the backend is working properly
-Self-signed SSL certificates are being blocked:
Fix this by turning off 'SSL certificate verification' in Settings > General
-Proxy configured incorrectly
Ensure that proxy is configured correctly in Settings > Proxy
-Request timeout:
Change request timeout in Settings > General
*vagrant file :
config.vm.network "forwarded_port", guest: 80, host: 8080, auto_correct:
true
config.vm.network "private_network", ip: "192.168.33.10"
config.vm.network "public_network"
you should run your bottle app on 0.0.0.0 to export it to "other" machines
app.run(host="0.0.0.0", port=80, reloader=True, debug=True) # ...
For me i proxy pass the internall server with nginx works well just make a configuration on nginx like this
server{
listen 85;
listen [::]:85;
server_name rsshistory.com;
location / {
proxy_pass http://127.0.0.1:8000/;
}
}
On the vagrant file, dont turn on all of that just do this
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine and only allow access
# via 127.0.0.1 to disable public access
# config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.$
# Create a private network, which allows host-only access to the machine
# using a specific IP.
config.vm.network "private_network", ip: "192.168.33.11"
Now you can access to the bottle server true 192.168.33.11:85

Can't Connect Node.js Thrift Client to Python Thrift Server

I'm trying to connect a nodejs thrift client to a python thrift server.
The python server is a multiplexed thrift server and works flawlessly with a python client.
Now I'm trying to add a node client to the game but so far I had no luck connecting it to the server.
var thrift = require('thrift')
var transport = thrift.TBufferedTransport;
var protocol = thrift.TBinaryProtocol;
var connection = thrift.createConnection("localhost", 8080, {
transport : thrift.TBufferedTransport,
protocol : thrift.TBinaryProtocol
});
connection.on('error', function(err) {
console.log(err);
});
...
..
.
It keeps failing at creating a connection and I'm getting the error message
{ Error: connect ECONNREFUSED 127.0.0.1:8080
at Object._errnoException (util.js:992:11)
at _exceptionWithHostPort (util.js:1014:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1186:14)
code: 'ECONNREFUSED',
errno: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 8080 }
I tested creating a connection between a node client and node server which worked without problems as well.
Thanks in advance!
I set up a minimal working example which threw the same error as well.
After checking with
nv -v localhost 8080 I was presented with a "connection refused" error as well.
Following change solved my issue:
Change (server.py)
transport = TSocket.TServerSocket(port=8080)
to
transport = TSocket.TServerSocket(host="127.0.0.1",port=8080)

Cannot access Flask with apache

I have a linux server which I am running my flask app on it like this:
flask run --host=0.0.0.0
Inside the server I can access it like this:
curl http://0.0.0.0:5000/photo (and I am getting a valid response)
However, when I am trying to access it outside the server:
http://my_ip:5000/photo - the connection is refused.
The same ip, will return an image saved on public_html with apache2 configured
http://my_ip/public_html/apple-touch-icon-144x144-precomposed.png
I use this simple snippet to get the ip-address from the interface
import socket
def get_ip_address():
""" get ip-address of interface being used """
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
return s.getsockname()[0]
IP = get_ip_address()
And in main:
if __name__ == '__main__':
app.run(host=IP, port=PORT, debug=False)
And running:
./app.py
* Running on http://10.2.0.41:1443/ (Press CTRL+C to quit)
I have a suspicion you have a firewall on your Linux machine that is blocking port 5000.
Solution 1:
Open the relevant port on your firewall.
Solution 2:
I would suggest you to install nginx as a web proxy and configure it so that http://my_ip/photo would forward traffic to and from http://127.0.0.1:5000/photo:
server {
listen 80;
location /photo {
proxy_pass http://127.0.0.1:5000/photo;
}
}

Connection error with Tornado Websockets + Django + Azure + Apache

I am running my application with Windows Azure on a Virtual Machine with ubuntu 14.04 lts. I am running my Django application through WSGI on Apache.
Previously i ran django locally with the command "python manage.py runserver", and every thing worked fine when my website connected to my sockets.py file from website.html.
I am running Django through Apache on public ip port 80
I am running the sockets.py separately in a terminal through Putty
I am reading the error through the Google Chrome console
Suddenly this error occurs: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state. whenever i try to connect to the socket.
After a while my page response with: failed: Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT
website.html js:
ws = new WebSocket("ws://10.77.22.74:1339/ws");
function load_all() {
target = "load_all"
ws.send(target)
}
ws.onmessage = function(evt) {
console.log(evt.data)
}
The ip is my internal ip on my virtual machine.
sockets.py:
import tornado.httpserver
import tornado.websocket
import tornado.ioloop
import tornado.web
class WSHandler(tornado.websocket.WebSocketHandler):
def check_origin(self, origin):
return True
def open(self):
print 'new connection'
def on_message(self, message):
self.write_message(message)
def on_close(self):
print 'connection closed'
application = tornado.web.Application([
(r'/ws', WSHandler),
])
if __name__ == "__main__":
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(1339)
tornado.ioloop.IOLoop.instance().start()
I have tried to change the http_server.listen(1339) to http_server.listen(1339, adress='10.77.22.74') (sockets.py)
I have tried using my public ip and opening a port through tcp (endpoints) and adjusting the scripts after that (sockets.py & website.html)
I have tried running with the localhost & 127.0.0.1 (sockets.py & website.html)
I have tried with ws & wss
I still get the error for some reason, do i need to give Apache (www-data) some permissions to connect to the sockets.py?
Which IP should i use, both on socket.py and website.htm?
Solved
Turn out Tornado is listening to all IP:s if you not specify the adress in the socket server. I opened a port on the public IP and used that IP for my javascript socket connection.

Categories