stilliard / docker-pure-ftpd

Docker Pure-ftpd Server
https://hub.docker.com/r/stilliard/pure-ftpd/
MIT License
857 stars 324 forks source link

How can I setup it up with Traefik? #98

Open sidneydemoraes opened 5 years ago

sidneydemoraes commented 5 years ago

Hi there. I'm trying to setup up this container to be used through Traefik. This is what I did.

  ftp-sgrio:
    image: stilliard/pure-ftpd:hardened
    restart: on-failure:3
    environment:
      FTP_USER_NAME: bla
      FTP_USER_PASS: blablabla
      FTP_USER_HOME: /var/www/html
      FTP_USER_UID: 33
      FTP_USER_GID: 33
      ADDED_FLAGS: "-d -d"
    expose:
      - "21"
    networks:
      - mynet
    labels:
      - "traefik.enable=true"
      - "traefik.port=21"
      - "traefik.frontend.rule=Host:mydomain.com"
      - "traefik.backend=myftp"
    volumes:
      ...

I'm able to connect to port 21 on my host but I can't manage to connect with Filezila. It just says "Waiting for welcome message" and then fails. What could be wrong?

stilliard commented 5 years ago

Hey @sidneydemoraes, Have you tried passing the PUBLICHOST environment variable? that can often cause connection issues if missing.

I've not used Traefik but it looks interesting, let me know how it goes setting it up with pure-ftpd.

sidneydemoraes commented 5 years ago

Hey @stilliard . Thanks for your prompt response. I did try with both my host IP and with my traefik network IP. Neither of them worked. I wish I found a way to debug what happens after I get into the host port 21. I can't tell if there's an issue in Traefik setup or in pureFTP inside the container.

stilliard commented 5 years ago

Hmm interesting, it looks like you can add logs to Traefik: https://docs.traefik.io/configuration/logs/ Maybe these can help shed some light on if it's even reaching the pureFTP container.

stilliard commented 5 years ago

With Traefik, are you able to access the host directly? might be worth trying to connect directly. or if you can exec into the pureftpd container you could see if there's anything logged with: tail -f /var/log/messages

Hope this helps.

sidneydemoraes commented 5 years ago

In fact, no logs are shown in pure-ftpd. I guess there's something to do with setting traefik ports and proxy them to the container. I'll let you know if I find something.

davidwneary commented 5 years ago

@sidneydemoraes did you manage to solve this?

acydburn commented 5 years ago

Traefik is an HTTP/HTTPS only proxy. No Streams/TCP support as far as i know. ;)

Maybe DeleGate (http://www.delegate.org/delegate/Manual.shtml?serv_FTP) is something you can use?

looztra commented 5 years ago

Traefik v2 does support TCP now (still in alpha)

EthraZa commented 4 years ago

The closer I could get was to login ok into FTP, but them the passive mode come and bite my ankle.

traefik-compose.yml:

command:
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --entrypoints.ftp.address=:21
      - ...

ftp-compose.yml:

deploy:
      labels:
        - "traefik.enable=true"
        - "traefik.docker.network=netweb"
        - "traefik.protocol=tcp"
        - "traefik.tcp.services.ftphost.loadbalancer.server.port=21"
        - "traefik.tcp.routers.ftphost.entrypoints=ftp"
        - "traefik.tcp.routers.ftphost.rule=HostSNI(`*`)"
ports:
      - target: 21
        protocol: tcp
        mode: ingress
      - "50000-50019"

I tryed to map the 50000-50019 ports as --entrypoints.pasv00.address=:5000 too, with traefik.tcp.routers.ftphost.entrypoints=ftp,pasv00, but no dice. I guess it needs something on loadbalancer.server.port too, but I don't know how to setup this one.

So, for now, I'm going to try to let the FTP service as mode:global and put some constraints on it, since I use syncthing to sync the folders, all server may look like one.

If someone learn how to deal with passive mode in the swarm, please remember to come back here and help us with some directions.

AntoineMicheaOpencell commented 4 years ago

Hi @EthraZa did you finally find a solution i also try to deploy this image on kubernetes cluster then use traefik v2.3 ingress. Active mode is working for you ? I also able to connect to ftp, but i can do anything even in active or passive mode. I will published passive ports on traefik entrypoints. Hi here log connexion :

500 I won't open a connection to 51.XXX.XXX.XXX (only to 10.2.0.75)
ftp: bind: Address already in use
ftp> passive
Passive mode on.
ftp> ls
227 Entering Passive Mode (51,XXX,XXX,XXX,117,52)
ftp: connect: Connection refused

Don't find anything on pureftp logs.

EthraZa commented 4 years ago

Hi, no, If Traefik can do FTP, I can't find how.

My solution was to remove traefik labels and point the FTP DNS name to the Host IP running the ftp service container. The ports 20/21 can be ingress type, it does not need to be host type.

frugan-dev commented 3 years ago

Hi there @EthraZa @AntoineMicheaOpencell , in the end did you manage to find a solution?

I am using this https://dockerswarm.rocks/traefik/ with Traefik v2.3.6 and these changes:

traefik-compose.yml:

ports:
  - target: 21
    published: 21
    mode: host
  - "30000-30009"
  ...
command:
  - --entrypoints.ftp.address=:21
  - --entrypoints.ftp-passive-0.address=:30000
  - --entrypoints.ftp-passive-1.address=:30001
  - --entrypoints.ftp-passive-2.address=:30002
  - --entrypoints.ftp-passive-3.address=:30003
  - --entrypoints.ftp-passive-4.address=:30004
  - --entrypoints.ftp-passive-5.address=:30005
  - --entrypoints.ftp-passive-6.address=:30006
  - --entrypoints.ftp-passive-7.address=:30007
  - --entrypoints.ftp-passive-8.address=:30008
  - --entrypoints.ftp-passive-9.address=:30009
  ...

ftp-compose.yml:

labels:
  - traefik.tcp.routers.pure-ftpd-ftp.entrypoints=ftp
  - traefik.tcp.routers.pure-ftpd-ftp.rule=HostSNI(`*`)
  - traefik.tcp.routers.pure-ftpd-ftp.service=pure-ftpd

  - traefik.tcp.routers.pure-ftpd-ftp-passive-0.entrypoints=ftp-passive-0
  - traefik.tcp.routers.pure-ftpd-ftp-passive-0.rule=HostSNI(`*`)
  - traefik.tcp.routers.pure-ftpd-ftp-passive-0.service=pure-ftpd-passive-0

  - traefik.tcp.routers.pure-ftpd-ftp-passive-1.entrypoints=ftp-passive-1
  - traefik.tcp.routers.pure-ftpd-ftp-passive-1.rule=HostSNI(`*`)
  - traefik.tcp.routers.pure-ftpd-ftp-passive-1.service=pure-ftpd-passive-1

  - traefik.tcp.routers.pure-ftpd-ftp-passive-2.entrypoints=ftp-passive-2
  - traefik.tcp.routers.pure-ftpd-ftp-passive-2.rule=HostSNI(`*`)
  - traefik.tcp.routers.pure-ftpd-ftp-passive-2.service=pure-ftpd-passive-2

  - traefik.tcp.routers.pure-ftpd-ftp-passive-3.entrypoints=ftp-passive-3
  - traefik.tcp.routers.pure-ftpd-ftp-passive-3.rule=HostSNI(`*`)
  - traefik.tcp.routers.pure-ftpd-ftp-passive-3.service=pure-ftpd-passive-3

  - traefik.tcp.routers.pure-ftpd-ftp-passive-4.entrypoints=ftp-passive-4
  - traefik.tcp.routers.pure-ftpd-ftp-passive-4.rule=HostSNI(`*`)
  - traefik.tcp.routers.pure-ftpd-ftp-passive-4.service=pure-ftpd-passive-4

  - traefik.tcp.routers.pure-ftpd-ftp-passive-5.entrypoints=ftp-passive-5
  - traefik.tcp.routers.pure-ftpd-ftp-passive-5.rule=HostSNI(`*`)
  - traefik.tcp.routers.pure-ftpd-ftp-passive-5.service=pure-ftpd-passive-5

  - traefik.tcp.routers.pure-ftpd-ftp-passive-6.entrypoints=ftp-passive-6
  - traefik.tcp.routers.pure-ftpd-ftp-passive-6.rule=HostSNI(`*`)
  - traefik.tcp.routers.pure-ftpd-ftp-passive-6.service=pure-ftpd-passive-6

  - traefik.tcp.routers.pure-ftpd-ftp-passive-7.entrypoints=ftp-passive-7
  - traefik.tcp.routers.pure-ftpd-ftp-passive-7.rule=HostSNI(`*`)
  - traefik.tcp.routers.pure-ftpd-ftp-passive-7.service=pure-ftpd-passive-7

  - traefik.tcp.routers.pure-ftpd-ftp-passive-8.entrypoints=ftp-passive-8
  - traefik.tcp.routers.pure-ftpd-ftp-passive-8.rule=HostSNI(`*`)
  - traefik.tcp.routers.pure-ftpd-ftp-passive-8.service=pure-ftpd-passive-8

  - traefik.tcp.routers.pure-ftpd-ftp-passive-9.entrypoints=ftp-passive-9
  - traefik.tcp.routers.pure-ftpd-ftp-passive-9.rule=HostSNI(`*`)
  - traefik.tcp.routers.pure-ftpd-ftp-passive-9.service=pure-ftpd-passive-9

  - traefik.tcp.services.pure-ftpd.loadbalancer.server.port=21

  - traefik.tcp.services.pure-ftpd-passive-0.loadbalancer.server.port=30000
  - traefik.tcp.services.pure-ftpd-passive-1.loadbalancer.server.port=30001
  - traefik.tcp.services.pure-ftpd-passive-2.loadbalancer.server.port=30002
  - traefik.tcp.services.pure-ftpd-passive-3.loadbalancer.server.port=30003
  - traefik.tcp.services.pure-ftpd-passive-4.loadbalancer.server.port=30004
  - traefik.tcp.services.pure-ftpd-passive-5.loadbalancer.server.port=30005
  - traefik.tcp.services.pure-ftpd-passive-6.loadbalancer.server.port=30006
  - traefik.tcp.services.pure-ftpd-passive-7.loadbalancer.server.port=30007
  - traefik.tcp.services.pure-ftpd-passive-8.loadbalancer.server.port=30008
  - traefik.tcp.services.pure-ftpd-passive-9.loadbalancer.server.port=30009
  ...

I am aware that this is not a very elegant solution.. and maybe there are some errors too (I'm new to Docker and Traefik), but I am able to login despite not displaying the folder list.

This is the Filezilla log (obfuscated for obvious reasons):

Stato:  Risoluzione dell'indirizzo IP ***.***.*** in corso
Stato:  Connessione a ***.***.***.***:21...
Stato:  Connessione stabilita, in attesa del messaggio di benvenuto...
Risposta:   220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
Risposta:   220-You are user number 4 of 5 allowed.
Risposta:   220-Local time is now 17:09. Server port: 21.
Risposta:   220-This is a private system - No anonymous login
Risposta:   220-IPv6 connections are also welcome on this server.
Risposta:   220 You will be disconnected after 15 minutes of inactivity.
Comando:    AUTH TLS
Risposta:   234 AUTH TLS OK.
Stato:  Inizializzazione TLS in corso...
Stato:  Verifica del certificato in corso...
Stato:  Connessione TLS stabilita.
Comando:    USER ***
Risposta:   331 User *** OK. Password required
Comando:    PASS **********
Risposta:   230 OK. Current directory is /
Comando:    OPTS UTF8 ON
Risposta:   200 OK, UTF-8 enabled
Comando:    PBSZ 0
Risposta:   200 PBSZ=0
Comando:    PROT P
Risposta:   200 Data protection level set to "private"
Stato:  Accesso effettuato
Stato:  Lettura elenco cartelle...
Comando:    PWD
Risposta:   257 "/" is your current location
Comando:    TYPE I
Risposta:   200 TYPE is now 8-bit binary
Comando:    PASV
Risposta:   227 Entering Passive Mode (***,***,***,***,117,53)
Comando:    MLSD
Errore: La connessione dati non può essere stabilita. ECONNREFUSED - Connessione rifiutata dal server
...

Do you have any suggestions?

frugan-dev commented 3 years ago

Hey guys, I finally got it to work!

@sidneydemoraes @stilliard @davidwneary @EthraZa @AntoineMicheaOpencell

These are the working versions:

traefik-compose.yml:

image: traefik:v2.3.6
ports:
      - target: 21
        published: 21
        mode: host
      # Short syntax "30000-30009" doesn't seem to work..
      - target: 30000
        published: 30000
        mode: host
      - target: 30001
        published: 30001
        mode: host
      - target: 30002
        published: 30002
        mode: host
      - target: 30003
        published: 30003
        mode: host
      - target: 30004
        published: 30004
        mode: host
      - target: 30005
        published: 30005
        mode: host
      - target: 30006
        published: 30006
        mode: host
      - target: 30007
        published: 30007
        mode: host
      - target: 30008
        published: 30008
        mode: host
      - target: 30009
        published: 30009
        mode: host
      ...
command:
      - --entrypoints.entrypoint-ftp.address=:21
      - --entrypoints.entrypoint-ftp-passive-0.address=:30000
      - --entrypoints.entrypoint-ftp-passive-1.address=:30001
      - --entrypoints.entrypoint-ftp-passive-2.address=:30002
      - --entrypoints.entrypoint-ftp-passive-3.address=:30003
      - --entrypoints.entrypoint-ftp-passive-4.address=:30004
      - --entrypoints.entrypoint-ftp-passive-5.address=:30005
      - --entrypoints.entrypoint-ftp-passive-6.address=:30006
      - --entrypoints.entrypoint-ftp-passive-7.address=:30007
      - --entrypoints.entrypoint-ftp-passive-8.address=:30008
      - --entrypoints.entrypoint-ftp-passive-9.address=:30009
      ...

ftp-compose.yml:

image: stilliard/pure-ftpd:latest
environment:
      PUBLICHOST: ${FTP_PUBLICHOST}
      ADDED_FLAGS: ${FTP_ADDED_FLAGS}
      FTP_USER_NAME: ${FTP_USER_NAME}
      FTP_USER_PASS: ${FTP_USER_PASS}
      FTP_USER_HOME: ${FTP_USER_HOME}
      FTP_USER_UID: ${FTP_USER_UID}
      FTP_USER_GID: ${FTP_USER_GID}
      FTP_PASSIVE_PORTS: ${FTP_PASSIVE_PORTS}
      FTP_MAX_CLIENTS: ${FTP_MAX_CLIENTS}
      FTP_MAX_CONNECTIONS: ${FTP_MAX_CONNECTIONS}
      TLS_CN: ${FTP_TLS_CN}
      TLS_ORG: ${FTP_TLS_ORG}
      TLS_C: ${FTP_TLS_C}
#https://github.com/stilliard/docker-pure-ftpd/issues/51
#https://linux.die.net/man/8/pure-ftpd
command: /run.sh -l puredb:/etc/pure-ftpd/pureftpd.pdb -E -j -P ${FTP_PUBLICHOST} -s -A -Z -H -4 -E
deploy:
  labels:
      # FTP is a TCP based service exclusively. There is no UDP component to FTP.
      - traefik.tcp.routers.router-ftp.entrypoints=entrypoint-ftp
      - traefik.tcp.routers.router-ftp.rule=HostSNI(`*`)
      - traefik.tcp.routers.router-ftp.service=service-ftp

      - traefik.tcp.routers.router-ftp-passive-0.entrypoints=entrypoint-ftp-passive-0
      - traefik.tcp.routers.router-ftp-passive-0.rule=HostSNI(`*`)
      - traefik.tcp.routers.router-ftp-passive-0.service=service-ftp-passive-0

      - traefik.tcp.routers.router-ftp-passive-1.entrypoints=entrypoint-ftp-passive-1
      - traefik.tcp.routers.router-ftp-passive-1.rule=HostSNI(`*`)
      - traefik.tcp.routers.router-ftp-passive-1.service=service-ftp-passive-1

      - traefik.tcp.routers.router-ftp-passive-2.entrypoints=entrypoint-ftp-passive-2
      - traefik.tcp.routers.router-ftp-passive-2.rule=HostSNI(`*`)
      - traefik.tcp.routers.router-ftp-passive-2.service=service-ftp-passive-2

      - traefik.tcp.routers.router-ftp-passive-3.entrypoints=entrypoint-ftp-passive-3
      - traefik.tcp.routers.router-ftp-passive-3.rule=HostSNI(`*`)
      - traefik.tcp.routers.router-ftp-passive-3.service=service-ftp-passive-3

      - traefik.tcp.routers.router-ftp-passive-4.entrypoints=entrypoint-ftp-passive-4
      - traefik.tcp.routers.router-ftp-passive-4.rule=HostSNI(`*`)
      - traefik.tcp.routers.router-ftp-passive-4.service=service-ftp-passive-4

      - traefik.tcp.routers.router-ftp-passive-5.entrypoints=entrypoint-ftp-passive-5
      - traefik.tcp.routers.router-ftp-passive-5.rule=HostSNI(`*`)
      - traefik.tcp.routers.router-ftp-passive-5.service=service-ftp-passive-5

      - traefik.tcp.routers.router-ftp-passive-6.entrypoints=entrypoint-ftp-passive-6
      - traefik.tcp.routers.router-ftp-passive-6.rule=HostSNI(`*`)
      - traefik.tcp.routers.router-ftp-passive-6.service=service-ftp-passive-6

      - traefik.tcp.routers.router-ftp-passive-7.entrypoints=entrypoint-ftp-passive-7
      - traefik.tcp.routers.router-ftp-passive-7.rule=HostSNI(`*`)
      - traefik.tcp.routers.router-ftp-passive-7.service=service-ftp-passive-7

      - traefik.tcp.routers.router-ftp-passive-8.entrypoints=entrypoint-ftp-passive-8
      - traefik.tcp.routers.router-ftp-passive-8.rule=HostSNI(`*`)
      - traefik.tcp.routers.router-ftp-passive-8.service=service-ftp-passive-8

      - traefik.tcp.routers.router-ftp-passive-9.entrypoints=entrypoint-ftp-passive-9
      - traefik.tcp.routers.router-ftp-passive-9.rule=HostSNI(`*`)
      - traefik.tcp.routers.router-ftp-passive-9.service=service-ftp-passive-9

      - traefik.tcp.services.service-ftp.loadbalancer.server.port=21

      - traefik.tcp.services.service-ftp-passive-0.loadbalancer.server.port=30000
      - traefik.tcp.services.service-ftp-passive-1.loadbalancer.server.port=30001
      - traefik.tcp.services.service-ftp-passive-2.loadbalancer.server.port=30002
      - traefik.tcp.services.service-ftp-passive-3.loadbalancer.server.port=30003
      - traefik.tcp.services.service-ftp-passive-4.loadbalancer.server.port=30004
      - traefik.tcp.services.service-ftp-passive-5.loadbalancer.server.port=30005
      - traefik.tcp.services.service-ftp-passive-6.loadbalancer.server.port=30006
      - traefik.tcp.services.service-ftp-passive-7.loadbalancer.server.port=30007
      - traefik.tcp.services.service-ftp-passive-8.loadbalancer.server.port=30008
      - traefik.tcp.services.service-ftp-passive-9.loadbalancer.server.port=30009
      ...

.env:

FTP_PUBLICHOST=111.222.333.444 # <-- This is where magic happens!
FTP_ADDED_FLAGS=--tls=2
FTP_USER_NAME=bob
FTP_USER_PASS=changeme
FTP_USER_HOME=/home/ftpusers/bob
FTP_USER_UID=
FTP_USER_GID=
FTP_PASSIVE_PORTS=30000:30009
FTP_MAX_CLIENTS=
FTP_MAX_CONNECTIONS=
FTP_TLS_CN=
FTP_TLS_ORG=
FTP_TLS_C=

Maybe something can be optimized..

bertrand-sifre commented 3 years ago

Thank for the solution pure-ftp work's with treafik.

But it's possible to enable TLS with treafik to use let'sencrypt conf ???

KiSchulte commented 3 years ago

Hi guys,

thank you for the discussion here. Actually, this and some others helped a lot while implementing a vsftp in Kubernetes on digital ocean. One thing I'm still facing is an issue with the pasv mode and directory listing. For some reason the listing is failing with connection issue in 2 of 3 cases. Anyone else has observed similar issues? And could maybe give me hint what still to check. It seems that the connections are mybe not closed correct and still be opend. So only after some time the connection works again. Could that be the case and how could I check this.

Cheers Kirsten

zarraozaga commented 2 years ago

Hi, following up on this. I am able to get FTP login working. But when it comes to passive, the FTP server replies its private ip address to the client through reverse proxy, which results in a timeout. Any possible way to add a traefik middleware to replace private ip with the reverse proxy ip? (Lets treat the FTP server as a blackbox).

ololukaszuk commented 1 year ago

Hi, following up on this. I am able to get FTP login working. But when it comes to passive, the FTP server replies its private ip address to the client through reverse proxy, which results in a timeout. Any possible way to add a traefik middleware to replace private ip with the reverse proxy ip? (Lets treat the FTP server as a blackbox).

You should setup public IP on the FTP server itself. In FileZilla this is described here -> https://wiki.filezilla-project.org/Network_Configuration#Passive_mode_2