Bedeutung von fsync() im sshfs+LUKS-Setup

Bedeutung von fsync() im sshfs+LUKS-Setup

Hintergrund:Ich untersuche Methoden für verschlüsselte Speicherung auf nicht vertrauenswürdigen Maschinen. Mein aktuelles Setup verwendet sshfs, um auf ein LUKS-verschlüsseltes Image auf demFernbedienungMaschine, die entschlüsselt wirdörtlichund als ext3 gemountet. (Wenn ich nur sshfs verwenden würde, könnte jemand, der Zugriff auf den Remote-Computer erhält, meine Daten sehen.) Hier ist mein Beispiel-Setup:

# On the local machine:
sshfs remote:/home/crypt /home/crypt
cryptsetup luksOpen /home/crypt/container.img container
mount /dev/mapper/container /home/crypt-open

# Place cleartext files in /home/crypt-open,
# then reverse the above steps to unmount.

Ich möchte dies gegen Netzwerkausfälle widerstandsfähig machen. Dazu möchte ich verstehen, was bei diesem Setup mit Caching/Pufferung passiert. Betrachten Sie diese beiden Befehle:

dd if=/dev/random of=/home/crypt-open/test.dat bs=1000000 count=100
dd if=/dev/random of=/home/crypt-open/test.dat bs=1000000 count=100 conv=fsync

Der erste Befehl kehrt sehr schnell zurück und ich kann am Netzwerkverkehr erkennen, dass die Daten nach der Rückkehr des Befehls noch immer übertragen werden. Der zweite Befehl scheint zu warten, bis die Datenübertragung abgeschlossen ist.

Konkrete Fragen:Welche Garantien gibt es fsync()bei diesem Setup? fsync()Wie weit entlang dieser Ebenen ist bei der Rückgabe die Synchronisierung der Daten garantiert? Und was kann ich tun, um sicherzustellen, dass die Synchronisierung bis zur Festplatte des Remote-Computers erfolgt?

--- /home/crypt-open on the local machine
|
| (ext3 fs)
|
--- /dev/mapper/container on the local machine
|
| (LUKS)
|
--- /home/crypt/container.img on the local machine
|
| (sshfs)
|
--- /home/crypt/container.img on the remote machine
|
| (ext3 fs)
|
--- hard drive on the remote machine

Antwort1

Ich würde annehmen, dass das schwächste Glied hier der SSHFS-Code ist -- der Rest ist im Kernel und wird ziemlich häufig verwendet, also ist es wahrscheinlich in Ordnung. Ich habe mir noch nie FUSE-Code angeschaut, also könnte da noch etwas anderes passieren, das ich übersehen habe, aber lautSSHFS-Quellcode, die SSHFS-Implementierung fsync()macht nicht viel, sie ruft lediglich flush()den IO-Stream auf.

static int sshfs_fsync(const char *path, int isdatasync,
                       struct fuse_file_info *fi)
{
    (void) isdatasync;
    return sshfs_flush(path, fi);
}

Bei sshfs.c:2551können wir sehen, dass die sshfs_flush()Funktion keinerlei Synchronisierungsbefehle an den Remote-Rechner sendet, die ein Fsync erzwingen. Ich glaube, das sshfs.sync_writeFlag bedeutet „Warten, bis Befehle an den Server gesendet werden, bevor vom Schreiben zurückgekehrt wird“, und nicht „Fsync auf dem Server bei jedem Schreiben“, weil diese zweite Bedeutung sehr merkwürdig wäre. Daher ist Ihre Fsync-Messung langsamer, weil sie durch die Netzwerkgeschwindigkeit und nicht durch die Geschwindigkeit der Remote-Festplatte behindert wird.

static int sshfs_flush(const char *path, struct fuse_file_info *fi)
{
    int err;
    struct sshfs_file *sf = get_sshfs_file(fi);
    struct list_head write_reqs;
    struct list_head *curr_list;

    if (!sshfs_file_is_conn(sf))
        return -EIO;

    if (sshfs.sync_write)
        return 0;

    (void) path;
    pthread_mutex_lock(&sshfs.lock);
    if (!list_empty(&sf->write_reqs)) {
        curr_list = sf->write_reqs.prev;
        list_del(&sf->write_reqs);
        list_init(&sf->write_reqs);
        list_add(&write_reqs, curr_list);
        while (!list_empty(&write_reqs))
            pthread_cond_wait(&sf->write_finished, &sshfs.lock);
    }
    err = sf->write_error;
    sf->write_error = 0;
    pthread_mutex_unlock(&sshfs.lock);
    return err;
}

Beachten Sie, dass es möglich ist, dass die Remote-SFTP-Implementierung tatsächlich fsync beim Schreiben ausführt, aber ich denke, das ist eigentlich nicht der Fall. Laut einer altenEntwurf des SFTP-Standards(das ist das Beste, was ich finden kann) Es gibt eine Möglichkeit, dieses Verhalten festzulegen:

7.9. attrib-bits and attrib-bits-valid
...
SSH_FILEXFER_ATTR_FLAGS_SYNC
       When the file is modified, the changes are written synchronously
       to the disk.

was bedeuten würde, dass dies nicht die Standardeinstellung ist (da es schneller ist, kein fsync zu verwenden). Laut diesem Standarddokument scheint es keine Möglichkeit zu geben, ein fsync für die Remote-Datei anzufordern, aber es sieht so aus, als ob OpenSSH dies als Erweiterung zu SFTP unterstützt.

/* SSH2_FXP_EXTENDED submessages */
struct sftp_handler extended_handlers[] = {
    ...
    { "fsync", "[email protected]", 0, process_extended_fsync, 1 },
    ...
};

static void
process_extended_fsync(u_int32_t id)
{
    int handle, fd, ret, status = SSH2_FX_OP_UNSUPPORTED;

    handle = get_handle();
    debug3("request %u: fsync (handle %u)", id, handle);
    verbose("fsync \"%s\"", handle_to_name(handle));
    if ((fd = handle_to_fd(handle)) < 0)
        status = SSH2_FX_NO_SUCH_FILE;
    else if (handle_is_ok(handle, HANDLE_FILE)) {
        ret = fsync(fd);
        status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
    }
    send_status(id, status);
}

Ich bezweifle, dass es schwierig wäre, diese Erweiterung abzufragen und fsync in SSHFS richtig zu unterstützen. Das scheint mir eine ziemlich vernünftige Vorgehensweise zu sein. Allerdings denke ich, dass es wahrscheinlich einfacher wäre, einfach die Netzwerkblockgeräteunterstützung von Linux zu verwenden, von der ich annehme, dass sie all diese Dinge richtig unterstützt (obwohl ich sie selbst nie verwendet habe, also könnte es schrecklich sein).

verwandte Informationen