### Description

It is impossible to create a follower index with a `$` character in its name (please note, it is possible to create a regular index with `$` in its name).

This could be reproduced by rest request:
```
PUT /my-index/_ccr/follow
{
    "remote_cluster": "my-remote-cluster",
    "leader_index": "my-index$follower"
}
```

or `CcrIntegTestCase`:

```
    public void testFollowIndex() throws Exception {
        assertAcked(leaderClient().admin().indices().prepareCreate("my$index"));
        setupRemoteCluster();
        final PutFollowAction.Request followRequest = putFollow("my$index", "my$index");
        followerClient().execute(PutFollowAction.INSTANCE, followRequest).get();
    }
```

This is happening as during initial follow phase we restore the leader cluster from the remote using a snapshot restore.
Corresponding request is created with index name added to `RestoreSnapshotRequest#renamePattern` (regexp) without escaping `$`.

x-pack/plugin/ccr/src/internalClusterTest/java/org/elasticsearch/xpack/ccr/IndexFollowingIT.java
.get();
            final String leaderUUID = leaderIndexClusterState.getState().metadata().index("index1").getIndexUUID();
            final RoutingTable leaderRoutingTable = leaderClient().admin()
                .cluster()
                .prepareState()
                .clear()
                .setIndices("index1")
                .setRoutingTable(true)
                .get()
                .getState()
                .routingTable();
            final String retentionLeaseId = retentionLeaseId(
                getFollowerCluster().getClusterName(),
                new Index("index2", followerUUID),
                getLeaderCluster().getClusterName(),
                new Index("index1", leaderUUID)
            );
            final IndexRoutingTable indexRoutingTable = leaderRoutingTable.index("index1");
            for (int i = 0; i < indexRoutingTable.size(); i++) {
                final ShardId shardId = indexRoutingTable.shard(i).shardId();
                leaderClient().execute(
                    RetentionLeaseActions.Remove.INSTANCE,
                    new RetentionLeaseActions.RemoveRequest(shardId, retentionLeaseId)
                ).get();
            }
        }, exceptions -> assertThat(exceptions.size(), greaterThan(0)));
    }
    public void testIndexDoesNotFallBehind() throws Exception {
        runFallBehindTest(() -> {}, exceptions -> assertThat(exceptions.size(), equalTo(0)));
    }