trojan-gfw / trojan

An unidentifiable mechanism that helps you bypass GFW.
https://trojan-gfw.github.io/trojan/
GNU General Public License v3.0
18.96k stars 3.04k forks source link

[BUG] Connection refused when I set "local_addr": "0.0.0.0" in server side. #118

Closed chaos-sudo closed 5 years ago

chaos-sudo commented 5 years ago

Trojan Version 1.12.3

Describe the bug I tested it by using this command curl -x socks5h://127.0.0.1:1080 https://google.com. It can work fine when "local_addr" is "::" in server's config file. However, The connection will be failed if I set "local_addr" to "0.0.0.0", and the client side's log shows that it "cannot establish connection to remote server mydomain.com:443: Connection refused".

I can access my webpage from any browser with my domain or the server's IP, which means the server's IP is not blocked by GFW.

Logs Nothing shows in server side when I use curl command above , but it will show some information when I use a browser with my domain or server's IP address:

Welcome to trojan 1.12.3 [2019-07-10 16:54:46] [WARN] trojan service (server) started at 0.0.0.0:443 [2019-07-10 16:55:25] [ALL] _client_IPv4address:44304 incoming connection [2019-07-10 16:55:26] [WARN] _client_IPv4address:44304 not trojan request, connecting to 127.0.0.1:80 [2019-07-10 16:55:26] [ALL] _client_IPv4address:44304 tunnel established [2019-07-10 16:55:36] [INFO] _client_IPv4address:44304 disconnected, 23064 bytes received, 479 bytes sent, lasted for 11 seconds

Client side's log when I use curl command above:

Welcome to trojan 1.12.3 [2019-07-11 11:05:58] [WARN] trojan service (client) started at 127.0.0.1:1080 [2019-07-11 11:06:12] [ALL] 127.0.0.1:53356 incoming connection [2019-07-11 11:06:12] [INFO] 127.0.0.1:53356 requested connection to google.com":443 [2019-07-11 11:06:14] [ERROR] 127.0.0.1:53356 cannot establish connection to remote server mydomain.com:443: Connection refused [2019-07-11 11:06:14] [INFO] 127.0.0.1:53356 disconnected, 0 bytes received, 210 bytes sent, lasted for 2 seconds

curl error:

curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to google.com:443

Environment Server OS: Ubuntu 19.04 Client OS: MacOS 10.14.5 and Ubuntu 19.04(I also tested it in the server side by running another instance with the client config file, but the bug still exist)

These are my configurations: Nginx:

server {
    listen 127.0.0.1:80 default_server;
    server_name [mydomain.com];
    location / {
        proxy_pass https://github.com/;
    }
}
server {
    listen 0.0.0.0:80;
    listen [::]:80;
    server_name _;
    return 301 https://[mydomain.com]$request_uri;
}

Server.json

{
    "run_type": "server",
    "local_addr": "0.0.0.0",
    "local_port": 443,
    "remote_addr": "127.0.0.1",
    "remote_port": 80,
    "password": [
        "[mypassword]"
    ],
    "log_level": 0,
    "ssl": {
        "cert": "/etc/letsencrypt/live/[mydomain.com]/cert.pem",
        "key": "/etc/letsencrypt/live/[mydomain.com]/privkey.pem",
        "key_password": "",
        "cipher": "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256",
        "prefer_server_cipher": true,
        "alpn": [
            "http/1.1"
        ],
        "reuse_session": true,
        "session_ticket": false,
        "session_timeout": 600,
        "plain_http_response": "",
        "curves": "",
        "dhparam": ""
    },
    "tcp": {
        "prefer_ipv4": false,
        "no_delay": true,
        "keep_alive": true,
        "fast_open": false,
        "fast_open_qlen": 20
    },
    "mysql": {
        "enabled": false,
        "server_addr": "127.0.0.1",
        "server_port": 3306,
        "database": "trojan",
        "username": "trojan",
        "password": ""
    }
}

Client.json(tested in server side)

{
    "run_type": "client",
    "local_addr": "127.0.0.1",
    "local_port": 1080,
    "remote_addr": "[mydomain.com]",
    "remote_port": 443,
    "password": [
        "[mypassword]"
    ],
    "log_level": 0,
    "ssl": {
        "verify": true,
        "verify_hostname": true,
        "cert": "/etc/letsencrypt/live/[mydomain.com]/cert.pem",
        "cipher": "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256",
        "sni": "",
        "alpn": [
            "http/1.1"
        ],
        "reuse_session": true,
        "session_ticket": false,
        "curves": ""
    },
    "tcp": {
    "prefer_ipv4": false,
        "no_delay": true,
        "keep_alive": true,
        "fast_open": false,
        "fast_open_qlen": 20
    }
}
chaos-sudo commented 5 years ago

@GreaterFire Could you please open this issue?

GreaterFire commented 5 years ago

@chaos-sudo yes. just a sec please

chaos-sudo commented 5 years ago

@chaos-sudo yes. just a sec please

Do I really need to check the BOX in 'x' way? So that you may open my issue.

GreaterFire commented 5 years ago

I helped you check the box.

GreaterFire commented 5 years ago

To answer your original question, does your server have an IPv6 address? That would be why you are experiencing this issue.

chaos-sudo commented 5 years ago

To answer your original question, does your server have an IPv6 address? That would be why you are experiencing this issue.

I did have the IPv6 address. Actually, it can work like a charm when the "local_addr" is "::", which means the whole connection is exactly on IPv6 mode.

I have been getting the same result by testing in several servers from different vendors, such as Vultr, DigitalOcean, etc., so I can rule out the possibility of causing this problem due to VPS's environment.

Here are my steps to reproduce this situation.

After installing a pristine OS(Ubuntu 19.04):

DOMAIN="mydomain.com"
apt update && apt upgrade
apt install trojan certbot nginx # This will give me a 1.10.0 trojan, but it doesn't matter because I will also get the same result by running the latest trojan.
openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
mkdir -p /var/lib/letsencrypt/.well-known
chgrp www-data /var/lib/letsencrypt
chmod g+s /var/lib/letsencrypt
cat <<EOF >/etc/nginx/snippets/letsencrypt.conf
location ^~ /.well-known/acme-challenge/ {
  allow all;
  root /var/lib/letsencrypt/;
  default_type "text/plain";
  try_files \$uri =404;
}
EOF
cat <<EOF >/etc/nginx/snippets/ssl.conf
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 30s;
add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
EOF
cat <<EOF >/etc/nginx/sites-available/default
server {
  listen 80;
  server_name $DOMAIN www.$DOMAIN;
  include snippets/letsencrypt.conf;
}
EOF
systemctl restart nginx
certbot certonly --agree-tos --email admin@$DOMAIN --webroot -w /var/lib/letsencrypt/ -d $DOMAIN -d www.$DOMAIN --non-interactive
cat <<EOF >/etc/nginx/sites-available/default
server {
    listen 127.0.0.1:80 default_server;
    server_name $DOMAIN;
    location / {
        proxy_pass https://github.com/;
    }
}
server {
    listen 0.0.0.0:80;
    listen [::]:80;
    server_name _;
    return 301 https://$DOMAIN\$request_uri;
}
EOF
systemctl restart nginx
HarukaMa commented 5 years ago

@chaos-sudo When you use :: the default behavior is to listen both on IPv4 and IPv6, but 0.0.0.0 will only listen on IPv4, so IPv6 would give you "refused" error.

GreaterFire commented 5 years ago

@chaos-sudo Maybe your operating system uses IPv6 by default. In that case, trojan will only try to connect to your IPv6 address. As @HarukaMa says, if you only listen on IPv4, your server will reject any IPv6 connections.

chaos-sudo commented 5 years ago

@chaos-sudo When you use :: the default behavior is to listen both on IPv4 and IPv6, but 0.0.0.0 will only listen on IPv4, so IPv6 would give you "refused" error.

So how can I use IPv4?

GreaterFire commented 5 years ago

You can type your IPv4 address in remote_addr and your domain name in sni in client configuration.

chaos-sudo commented 5 years ago

It works! Thank you guys! @GreaterFire @HarukaMa

GreaterFire commented 5 years ago

@chaos-sudo You are very welcome.