How to access a query twice in different template files?

You could cache the results for that page load. It should hit it in header.php, cache the object, and in index.php you can check availability.

Header

$custom_query = new WP_Query( $args );

if( $custom_query->have_posts() ) {

    // Cache Query before loop
    wp_cache_add( 'custom_query', $custom_query );

    while( $custom_query->have_posts() ) { 
       $custom_query->the_post();
        // Do some stuff, like the_permalink();
    }

    wp_reset_postdata();
}

Other Files

$custom_query = wp_cache_get( 'custom_query', $custom_query );

if( ! empty( $custom_query ) && $custom_query->have_posts() ) {

    while( $custom_query->have_posts() ) { 
       $custom_query->the_post();
        // Do some stuff, like the_permalink();
    }

    wp_reset_postdata();
}