How do I hide posts across all loops based on the value of a custom field?

This should do it, using pre_get_posts:

function wpse_275546_hide_distribution_post( $query ) {
    /* Don't filter posts in admin, or the current post when viewing a single post. */
    if ( ! is_admin() && ! ( $query->is_main_query() && is_single() ) ) {
        /**
         * Get current meta query if it exists, otherwise an empty array. 
         * This is to modifiy, so that we don't override any existing meta queries.
         */
        $meta_query = $query->get( 'meta_query' ) ?: array();

        /* Add meta query to find posts that do not have distribitions set to 1. */
        $meta_query[] = array(
            'key'     => 'distribution',
            'value'   => '1',
            'compare' => '!=',
        );

        /* Apply meta query. */
        $query->set( 'meta_query', $meta_query );
    }
}
add_action( 'pre_get_posts', 'wpse_275546_hide_distribution_post' );

One thing I wasn’t sure about was your use of is_single(). Do you still want to allow people to view the single post? If so, do you still want to hide it from any other possible loops, like widgets?

If you’re ok showing the posts everywhere when viewing a single post, then you can remove the $query->is_main_query() && part. I added that to ensure that the main post appeared on single post views, but still kept them hidden from secondary posts.