stdiscosrv error stream error: stream ID 1; INTERNAL_ERROR; received from peer

So I whipped up my own alpine docker image compiling syncthing with go and then tried to use this as the stdiscosrv discovery server on my local network. I’m currently building from git repository and am using stdiscosrv v1.29.0-rc.1.dev.11.g8bd6bdd3 “Gold Grasshopper” (go1.23.4 linux-amd64)

I attempting to run the stdiscosrv directly using https with acme.sh certificates without a reverse proxy. I obtained ecc certs for the domain using acme.sh with zero-ssl.

The stdiscosrv executable is started with the command line (this taken directly from the Dockerfile (entire dockerfile is given below):

CMD ${USER_HOME}/dev/syncthing/bin/stdiscosrv \
    --debug \
    --listen="${SERV_PORT}" \
    --db-dir="${USER_HOME}/db" \
    --cert="${USER_HOME}/certs/cert.pem" \
    --key="${USER_HOME}/certs/key.pem"

I’m receiving an error however using a syncthing client trying to use this discovery server:

global@https://disco.gohilton.com:8443: Post "https://disco.gohilton.com:8443": stream error: stream ID 1; INTERNAL_ERROR; received from peer

I have no idea if the INTERNAL error is due to the ecc certs or just some other variable.

Only other thing I’ve noticed is the records.db created on stdiscosrv launch is always 0 bytes.

I attempt connecting to the stdisoserv using the following options within the syncthing client: https://disco..com:8443 https://disco..com:8443?id=I2PMJWN-H5OKMKG-3JAGJVZ-YXSUGEJ-RPP7POJ-RWEIBAE-SKR7SJX-IBBJ3A4

My Dockerfile is shown below:

FROM alpine:latest
################################
#           Settings           #
################################
# Syncthing-Discovery Server

ENV SERV_PORT :8443
ENV DISCO_OPTS "--http"

################################
#            Setup             #
################################
ENV BUILD_REQUIREMENTS curl openssl git go
ENV REQUIREMENTS ca-certificates bash shadow
ENV PUID 6000
ENV PGID 6000
ENV USER_HOME /home/discosrv
ENV USERNAME discosrv
ENV USERGROUP discosrv
################################

###############################
#           Build             #
###############################
ARG VERSION v1.18.1
#ARG DOWNLOAD="https://github.com/syncthing/discosrv/releases/download/${VERSION}/stdiscosrv-linux-amd64-v1.18.1.tar.gz"
ARG DOWNLOADURL="https://github.com/syncthing/discosrv/releases/download/v1.18.1/stdiscosrv-linux-amd64-v1.18.1.tar.gz"
###############################

USER root

# setup
SHELL ["/bin/sh", "-c"]
RUN apk update \
        && apk upgrade \
        && apk add --no-cache ${BUILD_REQUIREMENTS} ${REQUIREMENTS} \
        && mkdir -p ${USER_HOME} \
        && addgroup -S -g ${PGID} ${USERGROUP} \
        && adduser \
           --disabled-password \
           --gecos "" \
           --home ${USER_HOME} \
           --ingroup ${USERGROUP} \
           --uid ${PUID} \
           ${USERNAME} \
        && echo "${USERNAME}:$(openssl rand 512 | openssl sha256 | awk '{print $2}')" | chpasswd \
        && chown -R ${USERNAME}:${USERGROUP} ${USER_HOME} \
        && git config --global user.name "${USERNAME}" \
        && git config --global user.email "${USERNAME}@gmail.com" \
        && git config --global color.ui auto

EXPOSE ${SERV_PORT}

HEALTHCHECK --interval=1m --timeout=10s \
  CMD nc -z localhost ${SERV_PORT} || exit 1

# install disco
# WORKDIR /tmp/
# RUN curl -Ls ${DOWNLOADURL} --output discosrv.tar.gz \
#   && tar -zxf discosrv.tar.gz \
#   && rm discosrv.tar.gz \
#   && mkdir -p ${USER_HOME}/server ${USER_HOME}/certs ${USER_HOME}/db \
#   && cp /tmp/*discosrv*/*discosrv ${USER_HOME}/server/discosrv \
#   && chown -R ${USERNAME}:${USERGROUP} ${USER_HOME}

# install synthing from git
WORKDIR ${USER_HOME}

ADD https://github.com/syncthing/syncthing/commits?per_page=1 latest_commit
RUN mkdir -p ${USER_HOME}/dev \
    && cd ${USER_HOME}/dev \
    && git clone https://github.com/syncthing/syncthing.git \
    && cd syncthing \
    && go run build.go

# cleanup
#RUN apk del ${BUILD_REQUIREMENTS} \
#  && rm -rf /var/cache/apk/* \
#  && rm -rf /tmp/*

#WORKDIR ${USER_HOME}
USER ${USERNAME}
VOLUME ${USER_HOME}/certs

# CMD ${USER_HOME}/server/discosrv \
CMD ${USER_HOME}/dev/syncthing/bin/stdiscosrv \
#    ${DISCO_OPTS} \
    --debug \
    --listen="${SERV_PORT}" \
    --db-dir="${USER_HOME}/db" \
    --cert="${USER_HOME}/certs/cert.pem" \
    --key="${USER_HOME}/certs/key.pem"

My build statement is the following:

sudo docker build -f './Dockerfile-alpine' -t disco:1.29.0 .

My compose for the image is the following:

  disco:
    build:
      context: .
      dockerfile: Dockerfile-alpine
    image: disco:1.29.0
    container_name: disco
    hostname: disco
    domainname: <domain>.com
    restart: unless-stopped
    tty: True
    stdin_open: True
    depends_on:
      swag:
        condition: service_healthy
    healthcheck:
      <<: *disco-healthcheck
    networks:
      - net
    ports:
      - 8443:8443
    environment:
      TZ: America/Chicago
      PUID: 6000
      PGID: 6000
    volumes:
      - /data/disco/db:/home/discosrv/db
      - /data/disco/certs:/home/discosrv/certs

My logs from the container when running:

2024/12/19 01:25:58 stdiscosrv v1.29.0-rc.1.dev.11.g8bd6bdd3 "Gold Grasshopper" (go1.23.4 linux-amd64) root@buildkitsandbox 2024-12-18 07:56:06 UTC
2024/12/19 01:25:58 Server device ID is I2PMJWN-H5OKMKG-3JAGJVZ-YXSUGEJ-RPP7POJ-RWEIBAE-SKR7SJX-IBBJ3A4
2024/12/19 01:25:58 Read 0 records from database
2024/12/19 01:27:24 104a3a793a43e605 POST / HTTP/2.0
2024/12/19 01:28:04 0d657903faa9e9d5 GET /?device=TDKPN7Z-OMBAXMV-PK65ZTP-UAPQDXB-IMJ3ZNT-HSQUVRJ-3BVRZYP-PAN7TQE HTTP/2.0
2024/12/19 01:30:58 Calculating statistics
2024/12/19 01:30:58 Flushing database
2024/12/19 01:30:58 Finished flushing database
2024/12/19 01:32:24 4bfe8a8f6f789702 POST / HTTP/2.0
2024/12/19 01:35:58 Calculating statistics
2024/12/19 01:35:58 Flushing database
2024/12/19 01:35:58 Finished flushing database

My cert.pem is the following:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            7c:9c:7d:ff:c6:f8:b8:89:c5:d4:9c:df:30:2a:b7:6d
        Signature Algorithm: ecdsa-with-SHA384
        Issuer: C = AT, O = ZeroSSL, CN = ZeroSSL ECC Domain Secure Site CA
        Validity
            Not Before: Dec 18 00:00:00 2024 GMT
            Not After : Mar 18 23:59:59 2025 GMT
        Subject: CN = disco.<domain>.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (384 bit)
                pub:
                    04:71:3d:38:45:af:a0:e6:24:6b:5f:09:a8:a0:44:
                    35:d1:8a:ef:4b:00:a4:53:7b:b9:d4:1e:a9:5d:42:
                    3e:c2:d9:72:b1:16:27:49:62:82:c3:86:95:43:47:
                    c8:71:40:a2:8b:1b:9f:43:1f:28:68:1e:27:32:39:
                    fe:b7:f2:fa:4b:67:d5:74:b2:8c:cc:c4:52:d6:da:
                    72:cf:eb:c3:0a:5d:d3:51:8e:55:2d:2c:28:55:8f:
                    26:95:3f:a1:a7:e6:20
                ASN1 OID: secp384r1
                NIST CURVE: P-384
        X509v3 extensions:
            X509v3 Authority Key Identifier:
                0F:6B:E6:4B:CE:39:47:AE:F6:7E:90:1E:79:F0:30:91:92:C8:5F:A3
            X509v3 Subject Key Identifier:
                EC:83:36:2B:73:A7:CF:0F:07:7F:24:37:D3:7B:0F:98:31:8B:45:30
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Certificate Policies:
                Policy: 1.3.6.1.4.1.6449.1.2.2.78
                  CPS: https://sectigo.com/CPS
                Policy: 2.23.140.1.2.1
            Authority Information Access:
                CA Issuers - URI:http://zerossl.crt.sectigo.com/ZeroSSLECCDomainSecureSiteCA.crt
                OCSP - URI:http://zerossl.ocsp.sectigo.com
            CT Precertificate SCTs:
                Signed Certificate Timestamp:
                    Version   : v1 (0x0)
                    Log ID    : CF:11:56:EE:D5:2E:7C:AF:F3:87:5B:D9:69:2E:9B:E9:
                                1A:71:67:4A:B0:17:EC:AC:01:D2:5B:77:CE:CC:3B:08
                    Timestamp : Dec 18 20:27:05.225 2024 GMT
                    Extensions: none
                    Signature : ecdsa-with-SHA256
                                30:45:02:20:4E:A9:C2:98:A5:94:83:D5:11:A5:71:52:
                                80:94:2F:53:9E:22:7A:E6:01:F6:B3:F4:6B:CA:AF:39:
                                17:DB:E4:99:02:21:00:F0:7B:F7:F0:B4:20:C9:32:E9:
                                05:40:E8:C5:96:4E:9C:C7:D3:6A:39:37:26:75:D9:1E:
                                FE:7E:71:14:B9:00:7C
                Signed Certificate Timestamp:
                    Version   : v1 (0x0)
                    Log ID    : CC:FB:0F:6A:85:71:09:65:FE:95:9B:53:CE:E9:B2:7C:
                                22:E9:85:5C:0D:97:8D:B6:A9:7E:54:C0:FE:4C:0D:B0
                    Timestamp : Dec 18 20:27:05.233 2024 GMT
                    Extensions: none
                    Signature : ecdsa-with-SHA256
                                30:45:02:21:00:E6:FA:68:38:7E:1A:DC:B3:A7:01:D7:
                                A8:96:49:35:20:3D:77:0F:F9:E8:F1:83:A6:A4:68:D0:
                                98:3C:4D:13:47:02:20:53:F3:DF:BF:17:33:75:5E:71:
                                4F:7F:DE:8B:A6:29:A6:BD:68:AC:38:78:E8:F1:A0:DA:
                                49:B0:DD:F0:8F:C9:C4
            X509v3 Subject Alternative Name:
                DNS:disco.<domain>.com
    Signature Algorithm: ecdsa-with-SHA384
    Signature Value:
        30:66:02:31:00:8c:21:ce:ba:c8:8c:e4:9f:72:ae:25:8c:5c:
        96:2f:ca:b8:48:63:30:62:c5:78:c0:fb:7d:07:68:66:85:17:
        d9:c9:8d:18:90:70:60:f1:bb:65:78:2d:69:bc:e4:c8:c8:02:
        31:00:a7:16:73:37:b5:6c:0d:ac:f9:15:26:0c:31:4f:86:2f:
        a5:f5:9f:b1:82:24:c9:5f:db:7b:e0:4e:ec:a9:b7:03:87:e4:
        b8:95:82:14:8c:bc:5d:fb:1a:7f:61:49:01:47

Any help would be great. I’m not sure how to debug this

Me neither. I would start by letting it use a self-created certificate – do you get the same error then? If you do, start looking at the container stuff or the build process. If you don’t, then I guess it’s some aspect of the cert it doesn’t like.

Well – I simplified the testing setup and ditched the docker container for a moment just running the stdiscosrv on the host.

I built the same way as the container from git sources but now running on the host as it’s a lot easier to debug

Using my own ecc certficates, I’m getting the same as docker container: global@https://disco.<domain>.com:8443: Post "https://disco.<domain>.com:8443": stream error: stream ID 1; INTERNAL_ERROR; received from peer

I then tried specifically using my own ecc certs with the connection string: https://disco.<domain>.com:8443/?id=I2PMJWN-H5OKMKG-3JAGJVZ-YXSUGEJ-RPP7POJ-RWEIBAE-SKR7SJX-IBBJ3A4

and I’m gettting same error.

I then decided to ditch my ecc certificates and just let stdiscoserv generate it’s own certificates starting the server via: sudo ./stdiscosrv --debug --db-dir=/home/kevdog/data/syncthing/db --listen=:8443

To my surprise when examining the self created cert.pem – it actually is an ecc certificate as well

 openssl x509 --no-out --text --in cert.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            8d:30:f0:30:b8:a9:60:f4
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: O = Syncthing, OU = Automatically Generated, CN = stdiscosrv
        Validity
            Not Before: Dec 19 00:00:00 2024 GMT
            Not After : Dec 14 00:00:00 2044 GMT
        Subject: O = Syncthing, OU = Automatically Generated, CN = stdiscosrv
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (384 bit)
                pub:
                    04:c2:ee:56:c7:71:12:77:3f:4b:90:51:b9:ce:0c:
                    5a:f4:a4:51:d8:ea:61:ac:53:b3:92:0c:c0:4a:c5:
                    bd:7d:e8:c2:38:e8:07:b8:9d:3d:39:13:c0:18:fa:
                    83:ef:62:07:c4:da:58:d9:b5:63:a5:0d:87:34:26:
                    6d:e7:46:ed:38:e6:85:c0:61:7a:d7:db:b6:85:f8:
                    97:62:7a:74:33:4e:25:72:0b:48:43:5e:74:ea:fe:
                    ce:f8:e7:5b:35:b3:f2
                ASN1 OID: secp384r1
                NIST CURVE: P-384
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Alternative Name:
                DNS:stdiscosrv
    Signature Algorithm: ecdsa-with-SHA256
    Signature Value:
        30:65:02:30:2b:7c:6b:5f:9c:ae:5e:d5:38:fc:01:68:5a:fa:
        c0:9e:e0:db:40:5f:59:2a:84:21:6f:c7:1e:fb:6d:e8:e8:c1:
        97:77:40:16:4c:fb:92:08:95:48:24:ee:79:c0:30:a9:02:31:
        00:9c:46:af:f5:c8:49:a3:4e:eb:65:4c:2f:c1:22:42:83:0a:
        af:23:95:07:eb:c3:86:51:56:60:57:73:56:0d:b4:1b:56:e9:
        7a:b8:1c:b6:5d:68:3c:28:3c:ab:a6:f5:cc
-----BEGIN CERTIFICATE-----
MIICIDCCAaagAwIBAgIJAI0w8DC4qWD0MAoGCCqGSM49BAMCMEsxEjAQBgNVBAoT
CVN5bmN0aGluZzEgMB4GA1UECxMXQXV0b21hdGljYWxseSBHZW5lcmF0ZWQxEzAR
BgNVBAMTCnN0ZGlzY29zcnYwHhcNMjQxMjE5MDAwMDAwWhcNNDQxMjE0MDAwMDAw
WjBLMRIwEAYDVQQKEwlTeW5jdGhpbmcxIDAeBgNVBAsTF0F1dG9tYXRpY2FsbHkg
R2VuZXJhdGVkMRMwEQYDVQQDEwpzdGRpc2Nvc3J2MHYwEAYHKoZIzj0CAQYFK4EE
ACIDYgAEwu5Wx3ESdz9LkFG5zgxa9KRR2OphrFOzkgzASsW9fejCOOgHuJ09ORPA
GPqD72IHxNpY2bVjpQ2HNCZt50btOOaFwGF619u2hfiXYnp0M04lcgtIQ1506v7O
+OdbNbPyo1YwVDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwFQYDVR0RBA4wDIIKc3RkaXNjb3NydjAK
BggqhkjOPQQDAgNoADBlAjArfGtfnK5e1Tj8AWha+sCe4NtAX1kqhCFvxx77bejo
wZd3QBZM+5IIlUgk7nnAMKkCMQCcRq/1yEmjTutlTC/BIkKDCq8jlQfrw4ZRVmBX
c1YNtBtW6Xq4HLZdaDwoPKum9cw=
-----END CERTIFICATE-----

Because it’s self-signed certificate, I used the connection string method from the client to attempt to connect to the server: https://disco.<domain>.com:8443/?id=QFTB6EX-2SA4XQS-CS2R72E-JSBNK4B-VZRYH32-FSAZYSG-UNB7T5S-5V6JAA4

And I’m still getting same error: global@https://disco.<domain>.com:8443/: Post "https://disco.<domain>.com:8443/": stream error: stream ID 1; INTERNAL_ERROR; received from peer

So that’s about what I have for now. There isn’t a container or build process to debug in this instance – I just built directly with go

In terms of reverse proxy: I ditched swag as part of my testing. Just installed nginx in the host, and unfortunately I’m just getting a 403 forbidden error

I can see the connection reaching the server and receive this error:

2024/12/19 12:49:23 7dcde97a541f4e19 GET /?device=TDKPN7Z-OMBAXMV-PK65ZTP-UAPQDXB-IMJ3ZNT-HSQUVRJ-3BVRZYP-PAN7TQE HTTP/1.1
2024/12/19 12:49:25 3d331829f630b131 POST / HTTP/1.1
2024/12/19 12:49:25 3d331829f630b131 no certificates: empty certificate header

So consulting the documentation:

  • The “X-SSL-Cert” HTTP header must be passed through with the PEM-encoded client SSL certificate. This will be present in POST requests and may be empty in GET requests from clients. If you see syncthing-discosrv outputting no certificates when receiving POST requests, that’s because the proxy is not passing this header through.
  • The proxy must request the client SSL certificate but not require it to be signed by a trusted CA.

So wait a minute I now need SSL client certificates as well??

You didn’t mention a reverse proxy – well, in fact you implied you were not using one. If you are then I don’t see how the certificates on the discovery server matters at all, and it should be running in -http mode. In fact, given that, I don’t really understand what you’re doing at all.

Syncthing is the client cert part of the equation, it’s not something you need to deal with apart from making sure they actually reach the discovery server.

I’m not trying to be cryptic here – I’m just trying to get the stdiscosrv running by any means. Methods I’ve tried:

  1. No reverse proxy - with generated and autogenerated certs – error listed above
  2. Reverse proxy - In this method stdiscoserv running in -http mode and I’m using nginx as the reverse proxy. Now it seems I’m getting a 404 error which as best as I can tell is because of lack of a client certificate. I’ve done reading on this and it seems it will accept any client certificate. (Ok I’ve self generated ssl-client certificates – no problem). But how do I configure nginx to pass the client certificate?? Perhaps I’m wrong and I don’t know what I’m doing – that for sure, however the documentation I quoted other than talking about client certificates doesn’t show how to use these certificates – I’m assuming the nginx proxy is passing the client certificate to the backend here.

I’m not trying to be cryptic or obtuse but I can’t get this damn server up and running. I’m open to any means possible.

Fascinating, I’m getting the same stream internal error in a trivial setup. Will troubleshoot. :sweat_smile:


There’s a bug in the current (unreleased) code that you’re building from, I’m fixing it.

As for nginx, there are config suggestions in the doc article on the discovery server, but indeed try without a proxy for a simpler setup. You don’t need to do anything with client certificates in any case.

A 404 return is what you get from the discovery server when asking for a device that is not currently registered.

I think I got my reverse proxy setup appropriately (finally), however I’m getting a 502, but the error log is:

2024/12/19 17:20:52 [error] 470661#470661: *341 upstream prematurely closed connection while reading response header from upstream, client: 10.0.1.184, server: disco.<domain>, request: "POST / HTTP/2.0", upstream: "http://10.0.1.161:8443/", host: "disco.<domain>.com"

That might be due to the broken implementation?? Not sure. We’ll have to wait for your fix.

Yup, try again with latest main.

Thanks for the correction. Just have a question however what I’m seeing in the output

My setup – Macbook as my client with the Global Announce Servers set to https://disco.<domain>.com:8443

My server – Run directly on VM host started by:

$ sudo ./stdiscosrv --debug --cert=…/certs/disco..com.cer --key=…/certs/disco..com.key --db-dir=…/data/syncthing/db --listen=:8443

Output: No error listed client side

Server Side debug module shows the following:

2024/12/20 09:50:12 stdiscosrv v1.29.0-rc.2.dev.1.g00e7161a "Gold Grasshopper" (go1.23.4 linux-amd64) kevdog@ubuntuiohyve161 2024-12-20 09:34:29 UTC
2024/12/20 09:50:12 Server device ID is I2PMJWN-H5OKMKG-3JAGJVZ-YXSUGEJ-RPP7POJ-RWEIBAE-SKR7SJX-IBBJ3A4
2024/12/20 09:50:12 Read 0 records from database
2024/12/20 09:50:43 http: TLS handshake error from 10.0.1.161:37300: client sent an HTTP request to an HTTPS server
2024/12/20 09:50:51 5e968bdeddec8e17 POST / HTTP/2.0
2024/12/20 09:50:51 5e968bdeddec8e17 announced Z2M6GO2-455NXSO-CQLJVBB-IIG5MPA-ERT636W-LUK3GUC-MUSIBP6-6UIVQQF [quic://10.0.1.184:22000 relay://213.138.110.176:22067/?id=2YTTF3Y-S3AB2IJ-UUJN5NH-JDRZQ5T-S4EDR4Q-CLENDTU-QNE76GZ-EZZS4AR tcp://10.0.1.184:22000]
2024/12/20 09:51:43 69920dec17db552c GET /?device=TDKPN7Z-OMBAXMV-PK65ZTP-UAPQDXB-IMJ3ZNT-HSQUVRJ-3BVRZYP-PAN7TQE HTTP/2.0
2024/12/20 09:55:12 Calculating statistics
2024/12/20 09:55:12 Flushing database
2024/12/20 09:55:12 Finished flushing database

Is the following expected?: 2024/12/20 09:50:43 http: TLS handshake error from 10.0.1.161:37300: client sent an HTTP request to an HTTPS server

I also tested with the nginx reverse proxy in front of the app, and this situation worked as well.

Thanks

It means someone tried to talk HTTP to it and failed. Presumably not your Syncthing instance as the addresses are different. :person_shrugging:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.