self-hosted server with CG-NAT problem

djmelman18 days ago

Hi I am having problem implementing traccar into my system. I dont have public IP 1:1 and my ISP is blocking ports because Im behind CG-NAT. Therefore I tried solving this with ngrok,cloudflare, tailscale and loophole. I failed with every try. Most promising for me is loophole where I was succesfull with Traccar Mobile client because of the osmand protocol which is http-based. It worked becasue all of those solutions i listed are basically doing HTTP/S tunneling.
The problem came when I tried using Sinotrack ST-901L tracking device. I think the problem is that this device is using h02 protocol with is tcp raw based and isnt compatible with the http tunnel. Therefore Id probably need TCP raw tunnel? Are there any solutions for me? Or should I pay my ISP for public IP address? Help would be much appreciated.
PS: I tried to configure the device to work on demo server and it works even with URL.

David Cole18 days ago

Unless you can get something your device can talk to - which is as you pointed out most like raw tcp on a port with an IP you're a bit stuck.

I'm not behind cg-nat, but have done the same, by using a oracle VPS with an ip and with tailscale, I put in a simple python tcp server (answers on port 5002 and sends any packets to an internal ip address via tail scale).

I did look at if a cloudflare worker or azure worker could create a tcp endpoint but generally they can't (at the time I put in my solution).

So essentially the python tcp server just forwards anything it receives on the public ip/port to my local traccar instance.

djmelman18 days ago

That would work but if I have to use VPS then Id just run the whole server on VPS. I know about that solution but Id like to not include VPS in my implementation for lowering the costs as much as possible since i have the server device already.

David Cole18 days ago

Granted. I’m using a free oracle vps.

I did try running traccar there. But the oracle gps has about 1gb ram. And traccar plus a db caused it to hang.

So running just a python web server is a lot less memory requirements.

djmelman18 days ago

Oh I didnt know it was free. That might actually work. Can u provide bit more detail about the tcp server u are running on that vps? I would like to try it when I have time.

David Cole18 days ago

It’s just a simple python script with a tcp listener.

Getting it to stay up and restart is dependent on how you run it. I actually run in docker so it can auto restart.

But a systemd service will also work.

import socket 
import threading 
import os

LOCAL_HOST = os.getenv("LOCAL_HOST",'0.0.0.0') # Local IP address to bind to 
#LOCAL_HOST = '0.0.0.0' # Local IP address to bind to 
port = 30175
LOCAL_PORT = int(os.getenv("LOCAL_PORT",port))  # Local port to listen on 
#LOCAL_PORT = 30175  # Local port to listen on 
REMOTE_HOST = os.getenv("REMOTE_HOST",'localhost') # Remote IP address to forward to 
REMOTE_PORT = int(os.getenv("REMOTE_PORT","5055")) # Remote port to forward to 
#REMOTE_PORT = 5055 # Remote port to forward to 

def handle_client(client_socket):
    remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    remote_socket.connect((REMOTE_HOST, REMOTE_PORT))
    
    while True: 
        try:
            data = client_socket.recv(1024) 
            if len(data) == 0:
                break 
            print(f"receiving data {len(data)} bytes")
            remote_socket.send(data)
            print("Data transmitted")
        except Exception as ex :
            print(f"exception received {ex}")
            continue
    
    remote_socket.close() 
    client_socket.close()

def start_forwarding(): 
    server_socket = socket.socket() #socket.AF_INET, socket.SOCK_STREAM) 
    server_socket.bind((LOCAL_HOST, LOCAL_PORT)) 
    server_socket.listen() 
    print(f"[*] Listening on {LOCAL_HOST}:{LOCAL_PORT} and forwarding to {REMOTE_HOST}:{REMOTE_PORT}")
    
    while True: 
        try:
            client_socket, addr = server_socket.accept() 
            print("connect")
            print(f"[*]Accepted connection from {addr[0]}:{addr[1]}")
        
            client_thread = threading.Thread(target=handle_client, args=(client_socket,)) 
            client_thread.start()
        except Exception as ex:
            print(f"start_forwarding exception  {ex}")
            continue
start_forwarding()
hypoclone17 days ago

Hello @David Cole, is there a reason you only tried traccar on the free 1gb OCI instance? are you aware you have up to 24gb free OCI instance if you select ampere CPU ?

David Cole17 days ago

Heading a bit off topic, but no, I wasn’t aware.

djmelman17 days ago

I tried it but I have a problem that the tcp_forwarder isnt accepting the communication on the socket i think. because as u can see in the picture im receiving packets from the tracker. Below is the script im using.

ubuntu@tcpforward:~$ cat tcp_forwarder.py
import socket
import threading
import os

LOCAL_HOST = os.getenv("LOCAL_HOST",'0.0.0.0') # Local IP address to bind to
port = 5013
LOCAL_PORT = int(os.getenv("LOCAL_PORT",port))  # Local port to listen on
REMOTE_HOST = os.getenv("REMOTE_HOST",'100.118.74.50') # Remote IP address to forward to
REMOTE_PORT = int(os.getenv("REMOTE_PORT","5055")) # Remote port to forward to
# Debug logging to confirm values
print(f"LOCAL_HOST: {LOCAL_HOST}, LOCAL_PORT: {LOCAL_PORT}")
print(f"REMOTE_HOST: {REMOTE_HOST}, REMOTE_PORT: {REMOTE_PORT}")

def handle_client(client_socket):
    remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    remote_socket.connect((REMOTE_HOST, REMOTE_PORT))

    while True:
        try:
            data = client_socket.recv(1024)
            if len(data) == 0:
                break
            print(f"receiving data {len(data)} bytes")
            remote_socket.send(data)
            print("Data transmitted")
        except Exception as ex :
            print(f"exception received {ex}")
            continue

    remote_socket.close()
    client_socket.close()

def start_forwarding():
    server_socket = socket.socket() #socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind((LOCAL_HOST, LOCAL_PORT))
    server_socket.listen()
    print(f"[*] Listening on {LOCAL_HOST}:{LOCAL_PORT} and forwarding to {REMOTE_HOST}:{REMOTE_PORT}")

    while True:
        try:
            client_socket, addr = server_socket.accept()
            print("connect")
            print(f"[*]Accepted connection from {addr[0]}:{addr[1]}")

            client_thread = threading.Thread(target=handle_client, args=(client_socket,))
            client_thread.start()
        except Exception as ex:
            print(f"start_forwarding exception  {ex}")
            continue
start_forwarding()

Snímka obrazovky 2025-02-06 192648.png

David Cole17 days ago

can you see port 5013 listening when you start the script? netstat --ln But if txpdump reporting traffic o 5013 then surely the script is running?

And what do all the print statements look like when it's running

djmelman17 days ago

Snímka obrazovky 2025-02-06 194025.png

Snímka obrazovky 2025-02-06 194155.png

David Cole17 days ago

So i just ran mine (with the traccar iphone client) connected to the ip of my oracle vps:

[*] Listening on 0.0.0.0:30175 and forwarding to 192.158.10.45:5055
connect
[*]Accepted connection from 999.999.999.99:53205
connect
[*]Accepted connection from 999.999.999.99:53206
receiving data 376 bytes
receiving data 408 bytes
Data transmitted
Data transmitted

Are you sure there's a connection allowed to the script from external?
I don;t know a command for sending a tcp packet to the 5013 port while on the machine to verify the script - before looking at the external connectivity.

djmelman17 days ago

There is connection from the outside to the script. Here are the rules on my vps even my iptables are adjusted for it and im receiving packets from the tracker as u can see in the earlier picture. I think its waiting at this line below to basically connect to my traccar server i think no?

 client_socket, addr = server_socket.accept()

Snímka obrazovky 2025-02-06 195735.png

David Cole17 days ago

yeah it does look like it's hanging there. You can see in mine

[*] Listening on 0.0.0.0:30175 and forwarding to 192.158.10.45:5055
connect

And it never times out?

djmelman17 days ago

No never.