SFTP - Serve only specific files


is it possible, to run an ssh server in golang to serve only specific files?

Here is sample code for starting an sftp server: https://github.com/pkg/sftp/blob/master/examples/request-server/main.go but i did not see any option to limit the directores or files, that are served / presented to the client.

I would like to start a server, that searches a directory recursively for every jpeg file (*.jpg) and serves these files to other hosts in the network via socket connection. This should be done in a secure way, so i thougth, that sftp could be the right choice for this, but i don’t know, if ssh / sftp protocol supports it in general.


Directory /home/sandreas/filestoserve contains:


Now i would like to serve only:


And skip:


Is this possible with sftp and golang (without tricks like symlinks etc) and if so how do i do this?
If this is not possible, what technology would you recommend for this task?

The public API for that sftp package does not seem to support using anything other than the actual filesystem.

There is nothing in the protocol that prohibits you doing what you want.

I would start by reading the package’s code and figuring out where actual file access is done. Fork the package and add your filter there. If possible, do so as an option (like the read only support) and then submit your new filtering capability back to the project.


thank you for your hints. Now i used the official examples and tried to implement a “CustomHandler” instead of “InMemHandler” for NewRequestServer, which works as expected for the file listing (filtered files can be listed via array parameter). But if i try to download a listed file with FileZilla it gets disconnected with error:

error while reading: received failure with description 'read graft.go: file already closed'

There seems to be something wrong with the file open and close logic, so here is a pastebin with my CustomHandler:


called with:

var matchingPaths []string
matchingPaths = append(matchingPaths, "graft.go")
matchingPaths = append(matchingPaths, "LICENSE")
matchingPaths = append(matchingPaths, "README.md")

root := sftphandler.CustomHandler(matchingPaths)
server := sftp.NewRequestServer(channel, root)

The “ReaderAt” (Line 291) seems to be the tricky part, i think the defer fp.Close() leads to the “file is already closed” error on the client side. If i do not close the file, it

Could you give me a hint how to fix that?

Line 302 (in func (f *memFile) ReaderAt() (io.ReaderAt, error)) is:

defer f.reader.Close()

This closes the file at the end of ReaderAt, which means the function that uses that reader is trying to read from a closed file.

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