Search code examples
pythonssltcpcentosiptables

Can't estabilish connection in TCP port from external host


Please, someone help me with this! I'am really struggling for hours by now. Don't know what to do anymore, searched every page everywhere, still no solution.

I have a Python script which listens on port 443 (https - TCP). It receives JSON POST messages by this port. The problem is that it's not receiving anything from external hosts, only from itself. I mean, when I simulate a POST using POSTMAN from an external host, it never answers:

(I masked my server IP with 'y.y.y.y' and a token from my script with 'xxxx')

didnt receive

But when I send the exactly same thing from inside my own server, it works perfectly. The code to send from inside my own server:

[root@rrpump bot]# curl -v -k -X POST -H "Content-Type: application/json" -H "Cache-Control: no-cache"  -d '{
> "update_id":10000,
> "message":{
>   "date":1441645532,
>   "chat":{
>      "last_name":"Test Lastname",
>      "id":1111111,
>      "type": "private",
>      "first_name":"Test Firstname",
>      "username":"Testusername"
>   },
>   "message_id":1365,
>   "from":{
>      "last_name":"Test Lastname",
>      "id":1111111,
>      "first_name":"Test Firstname",
>      "username":"Testusername"
>   },
>   "text":"/start"
> }
> }' "https://y.y.y.y/xxxx"

The successfull response:

* About to connect() to y.y.y.y port 443 (#0)
*   Trying y.y.y.y...
* Connected to y.y.y.y (y.y.y.y) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
*       subject: CN=y.y.y.y 1,O=Example Brooklyn Company,L=Brooklyn,ST=New York,C=US
*       start date: Mar 06 13:54:03 2018 GMT
*       expire date: Mar 06 13:54:03 2019 GMT
*       common name: y.y.y.y
*       issuer: CN=y.y.y.y,O=Example Brooklyn Company,L=Brooklyn,ST=New York,C=US
> POST /xxxx HTTP/1.1
> User-Agent: curl/7.29.0
> Host: y.y.y.y
> Accept: */*
> Content-Type: application/json
> Cache-Control: no-cache
> Content-Length: 392
>
* upload completely sent off: 392 out of 392 bytes
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: WebhookHandler/1.0 Python/3.6.4
< Date: Tue, 06 Mar 2018 16:52:55 GMT
<
* Closing connection 0

Already checked if it is trully listening in that port:

[root@rrpump bot]# lsof -i:443
COMMAND     PID USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
python3.6 30644 root    8u  IPv4 2785755157      0t0  TCP *:https (LISTEN)

Already checked the iptables as well (last 'ACCEPT' line):

[root@rrpump bot]# iptables --list
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited
           all  --  anywhere             anywhere
           tcp  --  anywhere             anywhere
           tcp  --  anywhere             anywhere             tcp dpt:pcsync-https
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:pcsync-https
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:https

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Firewall is also disabled:

[root@rrpump bot]# firewall-cmd --permanent --add-port=443/tcp
FirewallD is not running

I'am running it on CENTOS 7 64bits, US hostinger VPS server. What am I forgetting to check here??!


Solution

  • In iptables rules, you have reject rules befor accept rules for your script. They are never used because they are checked in the same order iptables list them. So kernel finds matching reject rule first. You have to move reject rules to the end of table, or move yours to the top (insert them using iptables -I instead of appending by iptables -A). Or remove reject rules, and set default policy for input chain to reject or drop).

    Also please keep in mind, that there are always some rules (at least default policies) for all tables on kernel level. So by disabling some system deamon, you not necessarily make your host wide open to all connections. Always refer to iptables --list if unsure.

    Oh, and there is this older solution for accepting/rejecting TCP connections based on content of files /etc/hosts.allow and /etc/hosts.deny. Please check if connections to 443 are allowed in one and not denied in the other.