var res = from H in db.Products
join C in db.customers on H.Username equals C.Username
where C.Username == H.Username
select H;
Results results = res.Single();
The code above makes an inner join between C and H (the where clause is not necessary) and results in all elements given back where an appropriately connected products and customers entry exist.
The select H "just" gives back all the data from the products. As you stated that you want a mix you need to do that differently.
I myself would be using an anonymous type (or a dto object).
For an anonymous type:
select new { Username = H.Username, Product = H.Product, EMail = C.EMail}
Put together:
var res = from H in db.Products
join C in db.customers on H.Username equals C.Username
where C.Username == H.Username
select new { Username = H.Username, Product = H.Product, EMail = C.EMail}
Results results = res.Single();
For a DTO (Data Transfer Object) you would create a class with public set/get properties and use select new myClass(){....} instead of the select new {}.
DTOs are better in terms of reuse and that you have less problems with writing the names wrong that you use, ....
Just simply using select H, C sadly can't work as Linq wants to return just single objects per row (and additionally always the same datatype). Thus you need to put a container around the objects you want to return. In this case either anonymous types or DTOs.