{"id":2981,"date":"2025-01-29T15:21:18","date_gmt":"2025-01-29T20:21:18","guid":{"rendered":"https:\/\/blog.lufamily.ca\/kang\/?p=2981"},"modified":"2025-02-18T09:07:54","modified_gmt":"2025-02-18T14:07:54","slug":"simple-file-transfer-not","status":"publish","type":"post","link":"https:\/\/blog.lufamily.ca\/kang\/2025\/01\/29\/simple-file-transfer-not\/","title":{"rendered":"Simple File Transfer &#8211; NOT"},"content":{"rendered":"\n<p>Recently I needed to transfer a private binary file from one household to my server. We wanted this transfer to remain private because the file contains sensitive content.<\/p>\n\n\n\n<p>In the past, I set up a WebDAV server using Apache2.4:<\/p>\n\n\n\n<p>First I had to enable the DAV modules using the following command line on my Ubuntu server:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>sudo a2enmod dav\nsudo a2enmod dav_fs<\/code><\/pre>\n\n\n\n<p>I already had a directory set up on my file system called: <code>\/mnt\/Sites\/public_share<\/code>. I made the following changes to my Apache2 configuration files.<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>&lt;VirtualHost *:80&gt;\n    ServerName share.lufamily.ca\n    RewriteEngine On\n    RewriteCond %{HTTPS} off\n    RewriteRule (.*) https:\/\/share.lufamily.ca\n&lt;\/VirtualHost&gt;\n\n&lt;VirtualHost *:443&gt;\n    ServerName share.lufamily.ca\n    ServerAdmin xxxxxxxx@gmail.com\n    DocumentRoot \/mnt\/Sites\/public_share\n\n    &lt;Directory \/mnt\/Sites\/public_share&gt;\n        AllowOverride All\n    &lt;\/Directory&gt;\n\n    &lt;Location \/&gt;\n        AuthType None\n        DAV On\n        Options +Indexes\n        RewriteEngine off\n    &lt;\/Location&gt;\n\n    Include \/home\/xxxxx....xxxxxxx\/ssl.lufamily.ca\n&lt;\/VirtualHost&gt;<\/code><\/pre>\n\n\n\n<p>I did not have any authentication, because I restricted access to this directory with an override <code>.htaccess<\/code> file which contains the following:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>&lt;IfModule mod_headers.c&gt;\n    Header set X-XSS-Protection \"1; mode=block\"\n    Header always append X-Frame-Options SAMEORIGIN\n    Header set X-Content-Type-Options nosniff\n    Header set X-Robots-Tag \"noindex, nofollow\"\n&lt;\/IfModule&gt;\n\n&lt;Files \".htaccess\"&gt;\n  Order Allow,Deny\n  Deny from all\n&lt;\/Files&gt;\n\n&lt;RequireAny&gt;\n    Require ip 192.168.0.0\/16\n    Require ip 172.16.0.0\/12\n    Require ip 10.0.0.0\/8\n\n    # Sending computer external IP\n    Require ip AAA.BBB.CCC.DDD\n&lt;\/RequireAny&gt;<\/code><\/pre>\n\n\n\n<p>With the above setup, the other party just needs to open up a Finder on macOS or a Files Explorer on Windows with the above URL of <code>https:\/\/share.lufamily.ca<\/code>, and copy, delete, and open files like they normally would. The access will be private because it is restricted by their external IP address. With macOS, copying many gigabytes via WebDAV posed no issues.<\/p>\n\n\n\n<p>Unfortunately, Windows is another matter. This worked for small files. For large files in the gigabytes range, Windows seemed to be stuck on 99% complete. This is because Windows locally caches the large transfer and reports it is 99% completed in a very short time, as the physical transfer catches up. But the actual time needed for the copying across the Internet is so long that Windows became confused thinking that we are copying a file that already exists yielding an unwanted error.<\/p>\n\n\n\n<p>I had to come up with an alternative. We briefly dabbled with the idea of using FTP, but after a few minutes, this was simply a non-starter. The FTP passive mode requires ports to be opened on my firewall which is unrealistic for a long-term solution.<\/p>\n\n\n\n<p>SFTP is a very secure protocol that uses OpenSSH. I also like this technique because the usage is more secure and will be governed by a pair of SSH Keys. The private key on the remote user side and the public key will be used to configure SSH on my server. I set up a <code>ssh<\/code> user called <code>sftpuser<\/code>. To prepare for this user to only have <code>sftp<\/code> access I made the following changes to the <code>sshd<\/code> configuration file <code>\/etc\/ssh\/sshd_config<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code># Added the internal-sftp\nSubsystem sftp \/usr\/lib\/openssh\/sftp-server internal-sftp\n\n# Configure the local user scpuser to only do sftp\nMatch User sftpuser\n    ChrootDirectory \/home\/sftpuser\n    PasswordAuthentication no\n    ForceCommand internal-sftp\n    AllowTcpForwarding no\n    X11Forwarding no\n    AllowAgentForwarding no<\/code><\/pre>\n\n\n\n<p>I then created the <code>sftpuser<\/code> using the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>sudo adduser sftpuser                                                                                                                  sudo chown root:root \/home\/sftpuser                                                                                                    \nsudo mkdir \/home\/sftpuser\/uploads                                                                                                      sudo chown sftpuser:sftpuser \/home\/sftpuser\/uploads                                                                                    \nsudo chmod -R 0755 \/home\/sftpuser\/uploads<\/code><\/pre>\n\n\n\n<p>This user will not be able to login into a shell and can only use <code>sftp<\/code>. I also disable the password authentication just in case. For the remote party to upload the file, they will need to provide a public <code>ssh<\/code> key which needs to be stored in the <code>.ssh\/authorized_keys<\/code> file. The contents of which look something like this:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCliK6NZx6JJBcK0+1GtEe8H6QpN1BHDRgq\/vtiEAfwzcjN1dBtQhfplyDxEXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXF+OLV9qWMsE\/g+1H4oyLRqzQnD8w7S4RBUJzrrZIpLEzYRf43pWSW9Y3220swlIEYxIOIcJIc8prgzDbECt3CR\/BsRDYNZA5uxdPYLwh1YtTX8GEqoctJifLrC4OomKkczDek9k\/MHdFbWZ0LdK3AB287nr\/Q4Lb8GgfU3bEhF+AMSWM8r\/OHC1QBPYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYbH8npyFsC3rADnjfFsB4VkkiNDDIZbZkV2vBf3sJ49Q1Y3uHugWxITWImKjfl+YUdGMalbSfP8UueKSx3sDGQQDXZjzrwnX3KPie0Qiz2rQtrppB7dA5CvOb86Q== guest<\/code><\/pre>\n\n\n\n<p>The above is just a single line in the file.<\/p>\n\n\n\n<p>With the above setup, a Linux user can simply do the following to transfer a file to my server in a very secure way.<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>sftp -P55522 sftpuser@lufamily.ca &lt;&lt;&lt; 'put \/usr\/bin\/bash uploads\/sample.bin'<\/code><\/pre>\n\n\n\n<p>The above command will upload the <code>bash<\/code> binary to my server.<\/p>\n\n\n\n<p>An attacker trying to login using ssh will get the following:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>\u276f ssh -p 55522 sftpuser@lufamily.ca\nThis service allows sftp connections only.\nConnection to lufamily.ca closed.<\/code><\/pre>\n\n\n\n<p>On Linux or macOS, the remote user can use <code>ssh-keygen<\/code> to create the public key which by default resides in <code>~\/.ssh\/id_dsa.pub<\/code>. All I need to do is copy the contents of the public key and add it to my <code>.ssh\/authorized_keys<\/code>.<\/p>\n\n\n\n<p>For Windows users, they can generate the key using Windows PowerShell. Below is an example:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>&gt; ssh-keygen -t rsa -b 4096\nGenerating public\/private rsa key pair.\nEnter file in which to save the key (C:\\Users\\kang\/.ssh\/id_rsa):\nEnter passphrase (empty for no passphrase):\nEnter same passphrase again:\nYour identification has been saved in C:\\Users\\kang\/.ssh\/id_rsa\nYour public key has been saved in C:\\Users\\kang\/.ssh\/id_rsa.pub\nThe key fingerprint is:\nSHA256:hV6vcChUwpxXXXXXXXXXXXXXXXXXXXXXXXXXX0aTkJZ2M kang@win10\nThe key's randomart image is:\n+---&#91;RSA 4096]----+\n|  . Eo.==..      |\n|   * *+++=+      |\n|  . @ oo.=+* .   |\n| . = o..B+=.* .  |\n|  .   .oSO.o..   |\n|       ..oo.     |\n|          .      |\n|                 |\n|                 |\n+----&#91;SHA256]-----+\n\n&gt; cat .\\.ssh\\id_rsa.pub\nssh-rsa AAAAB3NzaC1yc2EZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZQQWgIVShifqFxq78MWQEJrM2xrVQXlPHUncNosEm6P\/l0LdWu1nRbIccKMNsmpPK7JOv9XF+CsrtlltnhwDqiuflCGftzhrlmBz8BOJRiwD0Fl1IfQ+Qg7Z1nvIo6+kpkBw7SGPN7fbJxDPPHmc9iPB4RnlG46v6ymd4KM0h1cGlReCly2PTxTG1dcPuDbrBIIdEHoN\/40hojrooQf+cQNprvYZY59EjvC0NoZsfiKGDHHq3S7HRPGns9Oo4y8vFl1DrJZFIvBVdjjL28JsmIdeKbMhCynkzIkPLPvsiplxkEF0RQ9fFcIsucuD8leJmMDNPas+8EdueQ== kang@win10<\/code><\/pre>\n\n\n\n<p>To copy a binary you can do the following:<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>&gt; sftp -P55522 sftpuser@lufamily.ca\nConnected to lufamily.ca.\nsftp&gt; put \"C:\\Windows\\System32\\tar.exe\" uploads\/junk.exe\nUploading C:\/Windows\/System32\/tar.exe to \/uploads\/junk.exe\ntar.exe                                                                               100%   54KB  13.1MB\/s   00:00\nsftp&gt; ls\nuploads\nsftp&gt; cd uploads\nsftp&gt; ls\njunk.exe    sample.bin\nsftp&gt;<\/code><\/pre>\n\n\n\n<p>The above is very similar to Linux and the Mac. Windows and its PowerShell have come a long way in terms of adopting Posix-like capabilities.<\/p>\n\n\n\n<p>For those who want to use <a href=\"https:\/\/winscp.net\/eng\/index.php\" target=\"_blank\" rel=\"noreferrer noopener\">WinSCP<\/a>, a much nicer GUI on Windows, you will need to convert the <code>.ssh\/id_rsa<\/code> private key into <code>ppk<\/code> format. Use the command below to achieve this.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\"c:\\Program Files (x86)\\WinSCP\\WinSCP.com\" \/keygen id_rsa \/output=id_rsa.ppk<\/code><\/pre>\n\n\n\n<p>You can then set up <a href=\"https:\/\/winscp.net\/eng\/docs\/ui_login_authentication\" target=\"_blank\" rel=\"noreferrer noopener\">WinSCP authentication<\/a> and load the <code>ppk<\/code> file.<\/p>\n\n\n\n<p>So what I thought would be a simple matter turned out to be quite a deep rabbit hole. Hopefully with this in place, future transfers can be done quite quickly and securely.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently I needed to transfer a private binary file from one household to my server. We wanted this transfer to remain private because the file contains sensitive content. In the past, I set up a WebDAV server using Apache2.4: First I had to enable the DAV modules using the following command line on my Ubuntu &hellip; <a href=\"https:\/\/blog.lufamily.ca\/kang\/2025\/01\/29\/simple-file-transfer-not\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Simple File Transfer &#8211; NOT&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[111],"tags":[12,5,28],"class_list":["post-2981","post","type-post","status-publish","format-standard","hentry","category-tech","tag-it","tag-nas","tag-technology"],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p7V6i8-M5","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/blog.lufamily.ca\/kang\/wp-json\/wp\/v2\/posts\/2981","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.lufamily.ca\/kang\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.lufamily.ca\/kang\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.lufamily.ca\/kang\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.lufamily.ca\/kang\/wp-json\/wp\/v2\/comments?post=2981"}],"version-history":[{"count":16,"href":"https:\/\/blog.lufamily.ca\/kang\/wp-json\/wp\/v2\/posts\/2981\/revisions"}],"predecessor-version":[{"id":3011,"href":"https:\/\/blog.lufamily.ca\/kang\/wp-json\/wp\/v2\/posts\/2981\/revisions\/3011"}],"wp:attachment":[{"href":"https:\/\/blog.lufamily.ca\/kang\/wp-json\/wp\/v2\/media?parent=2981"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.lufamily.ca\/kang\/wp-json\/wp\/v2\/categories?post=2981"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.lufamily.ca\/kang\/wp-json\/wp\/v2\/tags?post=2981"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}